diff options
| author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-12 14:40:28 +0100 | 
|---|---|---|
| committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-12 14:40:28 +0100 | 
| commit | cf7af01aa77ec1b17687f5328ce0a598709efd59 (patch) | |
| tree | 4cc46339721366c7498dacf5ebac01906be273e7 | |
| parent | 6f341d14811550d863ba804ce6ec7757a7145081 (diff) | |
| parent | 5dcba5d6741d4533e0ef696507f93f2a4c738efb (diff) | |
| download | linux-cf7af01aa77ec1b17687f5328ce0a598709efd59.tar.bz2 | |
Merge branch 'topic/multi-component' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into for-2.6.37
340 files changed, 9234 insertions, 13384 deletions
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8b7201e4c79c..de40e9c787e1 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -295,6 +295,18 @@ static void davinci_init_wdt(void)  /*-------------------------------------------------------------------------*/ +struct platform_device davinci_pcm_device = { +	.name		= "davinci-pcm-audio", +	.id		= -1, +}; + +static void davinci_init_pcm(void) +{ +	platform_device_register(&davinci_pcm_device); +} + +/*-------------------------------------------------------------------------*/ +  struct davinci_timer_instance davinci_timer_instance[2] = {  	{  		.base		= DAVINCI_TIMER0_BASE, @@ -315,6 +327,7 @@ static int __init davinci_init_devices(void)  	/* please keep these calls, and their implementations above,  	 * in alphabetical order so they're easier to sort through.  	 */ +	davinci_init_pcm();  	davinci_init_wdt();  	return 0; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index b4ee5409eb72..b5261d44b263 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -732,9 +732,15 @@ static struct platform_device ep93xx_i2s_device = {  	.resource	= ep93xx_i2s_resource,  }; +static struct platform_device ep93xx_pcm_device = { +	.name		= "ep93xx-pcm-audio", +	.id		= -1, +}; +  void __init ep93xx_register_i2s(void)  {  	platform_device_register(&ep93xx_i2s_device); +	platform_device_register(&ep93xx_pcm_device);  }  #define EP93XX_SYSCON_DEVCFG_I2S_MASK	(EP93XX_SYSCON_DEVCFG_I2SONSSP | \ diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index e1f3efedbcf1..07690132cdbf 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -896,10 +896,16 @@ static struct platform_device kirkwood_i2s_device = {  	},  }; +static struct platform_device kirkwood_pcm_device = { +	.name		= "kirkwood-pcm", +	.id		= -1, +}; +  void __init kirkwood_audio_init(void)  {  	kirkwood_clk_ctrl |= CGC_AUDIO;  	platform_device_register(&kirkwood_i2s_device); +	platform_device_register(&kirkwood_pcm_device);  }  /***************************************************************************** diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 0f0823c8b170..379de9c59332 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -653,8 +653,8 @@ static struct clk_lookup lookups[] = {  	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1)  	_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk)  	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) -	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) -	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) +	_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) +	_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)  	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)  	_REGISTER_CLOCK(NULL, "vpu", vpu_clk)  	_REGISTER_CLOCK(NULL, "dma", dma_clk) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index a0aeb8a4adc1..2354d67a10db 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -415,7 +415,7 @@ struct platform_device mxc_usbh2 = {  	};								\  									\  	struct platform_device imx_ssi_device ## n = {			\ -		.name = "imx-ssi",					\ +		.name = "imx-ssi-dai",					\  		.id = n,						\  		.num_resources = ARRAY_SIZE(imx_ssi_resources ## n),	\  		.resource = imx_ssi_resources ## n,			\ diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c index 9a9eb6de6127..9b52a67abf2d 100644 --- a/arch/arm/mach-mx3/clock-imx31.c +++ b/arch/arm/mach-mx3/clock-imx31.c @@ -558,8 +558,8 @@ static struct clk_lookup lookups[] = {  	_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)  	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)  	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) -	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) -	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) +	_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) +	_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)  	_REGISTER_CLOCK(NULL, "firi", firi_clk)  	_REGISTER_CLOCK(NULL, "ata", ata_clk)  	_REGISTER_CLOCK(NULL, "rtic", rtic_clk) diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 9f3e943e2232..7b5acd5aa7c1 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -464,8 +464,8 @@ static struct clk_lookup lookups[] = {  	_REGISTER_CLOCK(NULL, "sdma", sdma_clk)  	_REGISTER_CLOCK(NULL, "spba", spba_clk)  	_REGISTER_CLOCK(NULL, "spdif", spdif_clk) -	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) -	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) +	_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk) +	_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)  	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)  	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)  	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index db7acd6e9101..27cfc39106a8 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -562,14 +562,14 @@ static struct resource imx_ssi_resources1[] = {  };  struct platform_device imx_ssi_device0 = { -	.name = "imx-ssi", +	.name = "imx-ssi-dai",  	.id = 0,  	.num_resources = ARRAY_SIZE(imx_ssi_resources0),  	.resource = imx_ssi_resources0,  };  struct platform_device imx_ssi_device1 = { -	.name = "imx-ssi", +	.name = "imx-ssi-dai",  	.id = 1,  	.num_resources = ARRAY_SIZE(imx_ssi_resources1),  	.resource = imx_ssi_resources1, diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 379100c17639..eb98eb8d3731 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -25,6 +25,7 @@  #include <mach/gpio.h>  #include <plat/mmc.h>  #include <plat/omap7xx.h> +#include <plat/mcbsp.h>  /*-------------------------------------------------------------------------*/ @@ -267,6 +268,30 @@ static inline void omap_init_sti(void)  static inline void omap_init_sti(void) {}  #endif +#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) + +static struct platform_device omap_pcm = { +	.name	= "omap-pcm-audio", +	.id	= -1, +}; + +OMAP_MCBSP_PLATFORM_DEVICE(1); +OMAP_MCBSP_PLATFORM_DEVICE(2); +OMAP_MCBSP_PLATFORM_DEVICE(3); + +static void omap_init_audio(void) +{ +	platform_device_register(&omap_mcbsp1); +	platform_device_register(&omap_mcbsp2); +	if (!cpu_is_omap7xx()) +		platform_device_register(&omap_mcbsp3); +	platform_device_register(&omap_pcm); +} + +#else +static inline void omap_init_audio(void) {} +#endif +  /*-------------------------------------------------------------------------*/  /* @@ -299,6 +324,7 @@ static int __init omap1_init_devices(void)  	omap_init_rtc();  	omap_init_spi100k();  	omap_init_sti(); +	omap_init_audio();  	return 0;  } diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3ccc34ebdcc7..04df912a7b55 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -20,6 +20,7 @@  #include <linux/i2c.h>  #include <linux/spi/spi.h>  #include <linux/usb/musb.h> +#include <sound/tlv320aic3x.h>  #include <asm/mach/arch.h>  #include <asm/mach-types.h> @@ -612,11 +613,25 @@ static int n8x0_menelaus_late_init(struct device *dev)  	return 0;  } +static struct aic3x_setup_data n810_aic33_setup = { +	.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, +	.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, +}; + +static struct aic3x_pdata n810_aic33_data = { +	.setup = &n810_aic33_setup, +	.gpio_reset = -1, +}; +  static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {  	{  		I2C_BOARD_INFO("menelaus", 0x72),  		.irq = INT_24XX_SYS_NIRQ,  	}, +	{ +		I2C_BOARD_INFO("tlv320aic3x", 0x1b), +		.platform_data = &n810_aic33_data, +	},  };  static struct menelaus_platform_data n8x0_menelaus_platform_data = { diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index abdf321c2d41..28978c08bced 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@  #include <linux/gpio.h>  #include <linux/gpio_keys.h>  #include <linux/mmc/host.h> +#include <sound/tlv320aic3x.h>  #include <plat/mcspi.h>  #include <plat/mux.h> @@ -686,7 +687,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {  }; -  static struct twl4030_platform_data rx51_twldata __initdata = {  	.irq_base		= TWL4030_IRQ_BASE,  	.irq_end		= TWL4030_IRQ_END, @@ -716,9 +716,21 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = {  	},  }; +/* Audio setup data */ +static struct aic3x_setup_data rx51_aic34_setup = { +	.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, +	.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, +}; + +static struct aic3x_pdata rx51_aic34_data = { +	.setup = &rx51_aic34_setup, +	.gpio_reset = 60, +}; +  static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {  	{  		I2C_BOARD_INFO("tlv320aic3x", 0x18), +		.platform_data = &rx51_aic34_data,  	},  }; diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c index 803ef14cbf2d..410fe006c0f6 100644 --- a/arch/arm/mach-omap2/board-zoom2.c +++ b/arch/arm/mach-omap2/board-zoom2.c @@ -14,6 +14,7 @@  #include <linux/platform_device.h>  #include <linux/input.h>  #include <linux/gpio.h> +#include <linux/i2c/twl.h>  #include <asm/mach-types.h>  #include <asm/mach/arch.h> @@ -34,8 +35,11 @@ static void __init omap_zoom2_init_irq(void)  	omap_gpio_init();  } -/* REVISIT: These audio entries can be removed once MFD code is merged */ -#if 0 +/* EXTMUTE callback function */ +void zoom2_set_hs_extmute(int mute) +{ +	gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); +}  static struct twl4030_madc_platform_data zoom2_madc_data = {  	.irq_line	= 1, @@ -43,6 +47,9 @@ static struct twl4030_madc_platform_data zoom2_madc_data = {  static struct twl4030_codec_audio_data zoom2_audio_data = {  	.audio_mclk = 26000000, +	.ramp_delay_value = 3,	/* 161 ms */ +	.hs_extmute = 1, +	.set_hs_extmute = zoom2_set_hs_extmute,  };  static struct twl4030_codec_data zoom2_codec_data = { @@ -64,10 +71,24 @@ static struct twl4030_platform_data zoom2_twldata = {  	.vmmc1          = &zoom2_vmmc1,  	.vmmc2          = &zoom2_vmmc2,  	.vsim           = &zoom2_vsim, +}; +static struct i2c_board_info __initdata zoom2_i2c_boardinfo[] = { +	{ +		I2C_BOARD_INFO("twl4030", 0x48), +		.flags = I2C_CLIENT_WAKE, +		.irq = INT_34XX_SYS_NIRQ, +		.platform_data = &zoom2_twldata, +	},  }; -#endif +static int __init omap3_zoom2_i2c_init(void) +{ +	omap_register_i2c_bus(1, 2600, zoom2_i2c_boardinfo, +			ARRAY_SIZE(zoom2_i2c_boardinfo)); +	return 0; +} +  #ifdef CONFIG_OMAP_MUX  static struct omap_board_mux board_mux[] __initdata = { @@ -81,6 +102,7 @@ static void __init omap_zoom2_init(void)  {  	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);  	zoom_peripherals_init(); +	omap3_zoom2_i2c_init();  	zoom_debugboard_init();  } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 03e6c9ed82a4..f9a5961d23a7 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -29,6 +29,7 @@  #include <mach/gpio.h>  #include <plat/mmc.h>  #include <plat/dma.h> +#include <plat/mcbsp.h>  #include "mux.h" @@ -289,6 +290,43 @@ static inline void omap_init_sti(void)  static inline void omap_init_sti(void) {}  #endif +#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) + +static struct platform_device omap_pcm = { +	.name	= "omap-pcm-audio", +	.id	= -1, +}; + +/* + * OMAP2420 has 2 McBSP ports + * OMAP2430 has 5 McBSP ports + * OMAP3 has 5 McBSP ports + * OMAP4 has 4 McBSP ports + */ +OMAP_MCBSP_PLATFORM_DEVICE(1); +OMAP_MCBSP_PLATFORM_DEVICE(2); +OMAP_MCBSP_PLATFORM_DEVICE(3); +OMAP_MCBSP_PLATFORM_DEVICE(4); +OMAP_MCBSP_PLATFORM_DEVICE(5); + +static void omap_init_audio(void) +{ +	platform_device_register(&omap_mcbsp1); +	platform_device_register(&omap_mcbsp2); +	if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) { +		platform_device_register(&omap_mcbsp3); +		platform_device_register(&omap_mcbsp4); +	} +	if (cpu_is_omap243x() || cpu_is_omap34xx()) +		platform_device_register(&omap_mcbsp5); + +	platform_device_register(&omap_pcm); +} + +#else +static inline void omap_init_audio(void) {} +#endif +  #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)  #include <plat/mcspi.h> @@ -901,6 +939,7 @@ static int __init omap2_init_devices(void)  	 * in alphabetical order so they're easier to sort through.  	 */  	omap_hsmmc_reset(); +	omap_init_audio();  	omap_init_camera();  	omap_init_mbox();  	omap_init_mcspi(); diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h index c93b29e21b78..b6a010fc8bda 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/include/mach/board-zoom.h @@ -3,3 +3,5 @@   */  extern int __init zoom_debugboard_init(void);  extern void __init zoom_peripherals_init(void); + +#define ZOOM2_HEADSET_EXTMUTE_GPIO	153 diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 8e10db148f1b..200c31a2730e 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -340,6 +340,31 @@ struct platform_device pxa_device_i2s = {  	.num_resources	= ARRAY_SIZE(pxai2s_resources),  }; +struct platform_device pxa_device_asoc_ssp1 = { +	.name		= "pxa-ssp-dai", +	.id		= 0, +}; + +struct platform_device pxa_device_asoc_ssp2= { +	.name		= "pxa-ssp-dai", +	.id		= 1, +}; + +struct platform_device pxa_device_asoc_ssp3 = { +	.name		= "pxa-ssp-dai", +	.id		= 2, +}; + +struct platform_device pxa_device_asoc_ssp4 = { +	.name		= "pxa-ssp-dai", +	.id		= 3, +}; + +struct platform_device pxa_device_asoc_platform = { +	.name		= "pxa-pcm-audio", +	.id		= -1, +}; +  static u64 pxaficp_dmamask = ~(u32)0;  struct platform_device pxa_device_ficp = { diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 93817d99761e..506fd5753ccc 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -37,4 +37,10 @@ extern struct platform_device pxa3xx_device_i2c_power;  extern struct platform_device pxa3xx_device_gcu; +extern struct platform_device pxa_device_asoc_platform; +extern struct platform_device pxa_device_asoc_ssp1; +extern struct platform_device pxa_device_asoc_ssp2; +extern struct platform_device pxa_device_asoc_ssp3; +extern struct platform_device pxa_device_asoc_ssp4; +  void __init pxa_register_device(struct platform_device *dev, void *data); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 0af36177ff08..465008293a25 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -384,6 +384,10 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)  static struct platform_device *devices[] __initdata = {  	&pxa27x_device_udc,  	&pxa_device_i2s, +	&pxa_device_asoc_ssp1, +	&pxa_device_asoc_ssp2, +	&pxa_device_asoc_ssp3, +	&pxa_device_asoc_platform,  	&sa1100_device_rtc,  	&pxa_device_rtc,  	&pxa27x_device_ssp1, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index f544e58e1536..f7a3b158ca97 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -597,6 +597,11 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)  static struct platform_device *devices[] __initdata = {  	&pxa27x_device_udc,  	&pxa_device_i2s, +	&pxa_device_asoc_ssp1, +	&pxa_device_asoc_ssp2, +	&pxa_device_asoc_ssp3, +	&pxa_device_asoc_ssp4, +	&pxa_device_asoc_platform,  	&sa1100_device_rtc,  	&pxa_device_rtc,  	&pxa27x_device_ssp1, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index c479cbecf784..5ba9d99a1bf6 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -45,6 +45,16 @@ int wm9713_irq;  int lcd_id;  int lcd_orientation; +struct platform_device pxa_device_wm9713_audio = { +	.name		= "wm9713-codec", +	.id		= -1, +}; + +static void __init zylonite_init_wm9713_audio(void) +{ +	platform_device_register(&pxa_device_wm9713_audio); +} +  static struct resource smc91x_resources[] = {  	[0] = {  		.start	= ZYLONITE_ETH_PHYS + 0x300, @@ -408,6 +418,7 @@ static void __init zylonite_init(void)  	zylonite_init_nand();  	zylonite_init_leds();  	zylonite_init_ohci(); +	zylonite_init_wm9713_audio();  }  MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index c3e9e73bd0f9..55ae1b0afae9 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c @@ -333,3 +333,16 @@ void __init s3c64xx_ac97_setup_gpio(int num)  	else  		s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;  } + +static u64 s3c_device_audio_dmamask = 0xffffffffUL; + +struct platform_device s3c_device_pcm = { +	.name		  = "s3c24xx-pcm-audio", +	.id		  = -1, +	.dev              = { +		.dma_mask = &s3c_device_audio_dmamask, +		.coherent_dma_mask = 0xffffffffUL +	} +}; +EXPORT_SYMBOL(s3c_device_pcm); + diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d9a03555f88b..362fc76ee726 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -256,6 +256,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {  	&s3c_device_fb,  	&s3c_device_ohci,  	&s3c_device_usb_hsotg, +	&s3c_device_pcm,  	&s3c64xx_device_iisv4,  #ifdef CONFIG_REGULATOR diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index 0c2cc5cd4d83..7c479e4fa999 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c @@ -49,9 +49,9 @@ static const char *audmux_port_string(int port)  {  	switch (port) {  	case MX31_AUDMUX_PORT1_SSI0: -		return "imx-ssi.0"; +		return "imx-ssi-dai.0";  	case MX31_AUDMUX_PORT2_SSI1: -		return "imx-ssi.1"; +		return "imx-ssi-dai.1";  	case MX31_AUDMUX_PORT3_SSI_PINS_3:  		return "SSI3";  	case MX31_AUDMUX_PORT4_SSI_PINS_4: diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index b4ff6a11a8f2..5b20103e68eb 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -30,6 +30,13 @@  #include <mach/hardware.h>  #include <plat/clock.h> +/* macro for building platform_device for McBSP ports */ +#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\ +static struct platform_device omap_mcbsp##port_nr = {	\ +	.name	= "omap-mcbsp-dai",			\ +	.id	= OMAP_MCBSP##port_nr,			\ +} +  #define OMAP7XX_MCBSP1_BASE	0xfffb1000  #define OMAP7XX_MCBSP2_BASE	0xfffb1800 diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 452e18438b41..9f8ee5e38615 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -481,7 +481,7 @@ static struct resource s3c_ac97_resource[] = {  	},  }; -static u64 s3c_device_ac97_dmamask = 0xffffffffUL; +static u64 s3c_device_audio_dmamask = 0xffffffffUL;  struct platform_device s3c_device_ac97 = {  	.name		  = "s3c-ac97", @@ -489,11 +489,37 @@ struct platform_device s3c_device_ac97 = {  	.num_resources	  = ARRAY_SIZE(s3c_ac97_resource),  	.resource	  = s3c_ac97_resource,  	.dev              = { -		.dma_mask = &s3c_device_ac97_dmamask, +		.dma_mask = &s3c_device_audio_dmamask,  		.coherent_dma_mask = 0xffffffffUL  	}  };  EXPORT_SYMBOL(s3c_device_ac97); +/* ASoC PCM DMA */ + +struct platform_device s3c_device_pcm = { +	.name		  = "s3c24xx-pcm-audio", +	.id		  = -1, +	.dev              = { +		.dma_mask = &s3c_device_audio_dmamask, +		.coherent_dma_mask = 0xffffffffUL +	} +}; + +EXPORT_SYMBOL(s3c_device_pcm); + +/* ASoC I2S */ + +struct platform_device s3c2412_device_iis = { +	.name		  = "s3c2412-iis", +	.id		  = -1, +	.dev              = { +		.dma_mask = &s3c_device_audio_dmamask, +		.coherent_dma_mask = 0xffffffffUL +	} +}; + +EXPORT_SYMBOL(s3c2412_device_iis); +  #endif // CONFIG_CPU_S32440 diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index e6144e4b9118..9ea6786d459d 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4;  extern struct platform_device s3c64xx_device_spi0;  extern struct platform_device s3c64xx_device_spi1; +extern struct platform_device s3c_device_pcm; +  extern struct platform_device s3c64xx_device_pcm0;  extern struct platform_device s3c64xx_device_pcm1; diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 9535ce68caae..83c3218cb4da 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -286,6 +286,7 @@  		ssi@16100 {  			compatible = "fsl,mpc8610-ssi"; +			status = "disabled";  			cell-index = <1>;  			reg = <0x16100 0x100>;  			interrupt-parent = <&mpic>; diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/fsl_guts.h index 0f165e59c326..bebd12463ec9 100644 --- a/arch/powerpc/include/asm/immap_86xx.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -1,5 +1,5 @@  /** - * MPC86xx Internal Memory Map + * Freecale 85xx and 86xx Global Utilties register set   *   * Authors: Jeff Brown   *          Timur Tabi <timur@freescale.com> @@ -10,73 +10,112 @@   * 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 header file defines structures for various 86xx SOC devices that are - * used by multiple source files.   */ -#ifndef __ASM_POWERPC_IMMAP_86XX_H__ -#define __ASM_POWERPC_IMMAP_86XX_H__ +#ifndef __ASM_POWERPC_FSL_GUTS_H__ +#define __ASM_POWERPC_FSL_GUTS_H__  #ifdef __KERNEL__ -/* Global Utility Registers */ -struct ccsr_guts { +/* + * These #ifdefs are safe because it's not possible to build a kernel that + * runs on e500 and e600 cores. + */ + +#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx) +#error Only 85xx and 86xx SOCs are supported +#endif + +/** + * Global Utility Registers. + * + * Not all registers defined in this structure are available on all chips, so + * you are expected to know whether a given register actually exists on your + * chip before you access it. + * + * Also, some registers are similar on different chips but have slightly + * different names.  In these cases, one name is chosen to avoid extraneous + * #ifdefs. + */ +#ifdef CONFIG_PPC_85xx +struct ccsr_guts_85xx { +#else +struct ccsr_guts_86xx { +#endif  	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */  	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */  	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */  	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */  	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */ -	u8	res1[0x20 - 0x14]; +	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */ +	u8	res018[0x20 - 0x18];  	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */ -	u8	res2[0x30 - 0x24]; +	u8	res024[0x30 - 0x24];  	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */ -	u8	res3[0x40 - 0x34]; +	u8	res034[0x40 - 0x34];  	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */ -	u8	res4[0x50 - 0x44]; +	u8	res044[0x50 - 0x44];  	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */ -	u8	res5[0x60 - 0x54]; +	u8	res054[0x60 - 0x54];  	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */ -	u8	res6[0x70 - 0x64]; +        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */ +        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */ +        u8	res06c[0x70 - 0x6c];  	__be32	devdisr;	/* 0x.0070 - Device Disable Control */  	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */ -	u8	res7[0x80 - 0x78]; +	u8	res078[0x7c - 0x78]; +	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */  	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */ -	u8	res8[0x90 - 0x84]; +	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */ +	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */ +	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */  	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */  	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */ -	u8	res9[0xA0 - 0x98]; +	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */ +	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */  	__be32	pvr;		/* 0x.00a0 - Processor Version Register */  	__be32	svr;		/* 0x.00a4 - System Version Register */ -	u8	res10[0xB0 - 0xA8]; +	u8	res0a8[0xb0 - 0xa8];  	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */ -	u8	res11[0xC0 - 0xB4]; +	u8	res0b4[0xc0 - 0xb4]; +#ifdef CONFIG_PPC_85xx +	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register */ +#else  	__be32	elbcvselcr;	/* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ -	u8	res12[0x800 - 0xC4]; +#endif +	u8	res0c4[0x224 - 0xc4]; +	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */ +	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */ +	u8	res22c[0x800 - 0x22c];  	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */ -	u8	res13[0x900 - 0x804]; +	u8	res804[0x900 - 0x804];  	__be32	ircr;		/* 0x.0900 - Infrared Control Register */ -	u8	res14[0x908 - 0x904]; +	u8	res904[0x908 - 0x904];  	__be32	dmacr;		/* 0x.0908 - DMA Control Register */ -	u8	res15[0x914 - 0x90C]; +	u8	res90c[0x914 - 0x90c];  	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */ -	u8	res16[0xB20 - 0x918]; +	u8	res918[0xb20 - 0x918];  	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */  	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */  	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */ -	u8	res17[0xE00 - 0xB2C]; +	u8	resb2c[0xe00 - 0xb2c];  	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */ -	u8	res18[0xE10 - 0xE04]; +	u8	rese04[0xe10 - 0xe04];  	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */ -	u8	res19[0xE20 - 0xE14]; +	u8	rese14[0xe20 - 0xe14];  	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */ -	u8	res20[0xF04 - 0xE24]; +	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */ +	u8	rese28[0xf04 - 0xe28];  	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */  	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */ -	u8	res21[0xF40 - 0xF0C]; -	__be32	srds2cr0;	/* 0x.0f40 - SerDes1 Control Register 0 */ -	__be32	srds2cr1;	/* 0x.0f44 - SerDes1 Control Register 0 */ +	u8	resf0c[0xf2c - 0xf0c]; +	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */ +	u8	resf30[0xf40 - 0xf30]; +	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */ +	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */  } __attribute__ ((packed)); +#ifdef CONFIG_PPC_86xx +  #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */  #define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */ @@ -93,7 +132,7 @@ struct ccsr_guts {   * ch: The channel on the DMA controller (0, 1, 2, or 3)   * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)   */ -static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, +static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,  	unsigned int co, unsigned int ch, unsigned int device)  {  	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); @@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,   * ch: The channel on the DMA controller (0, 1, 2, or 3)   * value: the new value for the bit (0 or 1)   */ -static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, +static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,  	unsigned int co, unsigned int ch, unsigned int value)  {  	if ((ch == 0) || (ch == 3)) { @@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,  #define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF  #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) -#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ -#endif /* __KERNEL__ */ +#endif + +#endif +#endif diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 4f9b2afc24e8..014dd4ad0d4f 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = {  	.probe		= twl4030_vibra_probe,  	.remove		= __devexit_p(twl4030_vibra_remove),  	.driver		= { -		.name	= "twl4030_codec_vibra", +		.name	= "twl4030-vibra",  		.owner	= THIS_MODULE,  #ifdef CONFIG_PM  		.pm	= &twl4030_vibra_pm_ops, @@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void)  }  module_exit(twl4030_vibra_exit); -MODULE_ALIAS("platform:twl4030_codec_vibra"); +MODULE_ALIAS("platform:twl4030-vibra");  MODULE_DESCRIPTION("TWL4030 Vibra driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 720e099e506d..5d0fb60a4c14 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)  	if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {  		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; -		child = add_child(sub_chip_id, "twl4030_codec", +		child = add_child(sub_chip_id, "twl4030-audio",  				pdata->codec, sizeof(*pdata->codec),  				false, 0, 0);  		if (IS_ERR(child))  			return PTR_ERR(child);  	} -	/* Phoenix*/ +	/* Phoenix codec driver is probed directly atm */  	if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {  		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; -		child = add_child(sub_chip_id, "twl6040_codec", +		child = add_child(sub_chip_id, "twl6040-codec",  				pdata->codec, sizeof(*pdata->codec),  				false, 0, 0);  		if (IS_ERR(child)) diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index add6f67d8032..9a4b196d6deb 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c @@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)  	if (pdata->audio) {  		cell = &codec->cells[childs]; -		cell->name = "twl4030_codec_audio"; +		cell->name = "twl4030-codec";  		cell->platform_data = pdata->audio;  		cell->data_size = sizeof(*pdata->audio);  		childs++;  	}  	if (pdata->vibra) {  		cell = &codec->cells[childs]; -		cell->name = "twl4030_codec_vibra"; +		cell->name = "twl4030-vibra";  		cell->platform_data = pdata->vibra;  		cell->data_size = sizeof(*pdata->vibra);  		childs++; @@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev)  	return 0;  } -MODULE_ALIAS("platform:twl4030_codec"); +MODULE_ALIAS("platform:twl4030-audio");  static struct platform_driver twl4030_codec_driver = {  	.probe		= twl4030_codec_probe,  	.remove		= __devexit_p(twl4030_codec_remove),  	.driver		= {  		.owner	= THIS_MODULE, -		.name	= "twl4030_codec", +		.name	= "twl4030-audio",  	},  }; diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 6de90bfc6acd..4793d8a7f480 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);  extern int twl4030_remove_script(u8 flags);  struct twl4030_codec_audio_data { -	unsigned int	audio_mclk; +	unsigned int audio_mclk; /* not used, will be removed */ +	unsigned int digimic_delay; /* in ms */  	unsigned int ramp_delay_value; +	unsigned int offset_cncl_path; +	unsigned int check_defaults:1; +	unsigned int reset_registers:1;  	unsigned int hs_extmute:1;  	void (*set_hs_extmute)(int mute);  }; diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 9d51d6f35893..3fd6456d07d7 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -114,7 +114,7 @@ struct sh_fsi_platform_info {  	int (*set_rate)(int is_porta, int rate); /* for master mode */  }; -extern struct snd_soc_dai fsi_soc_dai[2]; -extern struct snd_soc_platform fsi_soc_platform; +extern struct snd_soc_dai_driver fsi_soc_dai[2]; +extern struct snd_soc_platform_driver fsi_soc_platform;  #endif /* __SOUND_FSI_H */ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 377693a14385..e7b680248006 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -91,15 +91,17 @@ struct snd_pcm_substream;                                 SNDRV_PCM_FMTBIT_S32_LE |\                                 SNDRV_PCM_FMTBIT_S32_BE) -struct snd_soc_dai_ops; +struct snd_soc_dai_driver;  struct snd_soc_dai;  struct snd_ac97_bus_ops;  /* Digital Audio Interface registration */ -int snd_soc_register_dai(struct snd_soc_dai *dai); -void snd_soc_unregister_dai(struct snd_soc_dai *dai); -int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); -void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); +int snd_soc_register_dai(struct device *dev, +		struct snd_soc_dai_driver *dai_drv); +void snd_soc_unregister_dai(struct device *dev); +int snd_soc_register_dais(struct device *dev, +		struct snd_soc_dai_driver *dai_drv, size_t count); +void snd_soc_unregister_dais(struct device *dev, size_t count);  /* Digital Audio Interface clocking API.*/  int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, @@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);  /* Digital Audio Interface mute */  int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); -/* - * Digital Audio Interface. - * - * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 - * operations and capabilities. Codec and platform drivers will register this - * structure for every DAI they have. - * - * This structure covers the clocking, formating and ALSA operations for each - * interface. - */  struct snd_soc_dai_ops {  	/*  	 * DAI clocking configuration, all optional. @@ -191,24 +183,24 @@ struct snd_soc_dai_ops {  };  /* - * Digital Audio Interface runtime data. + * Digital Audio Interface Driver.   * - * Holds runtime data for a DAI. + * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 + * operations and capabilities. Codec and platform drivers will register this + * structure for every DAI they have. + * + * This structure covers the clocking, formating and ALSA operations for each + * interface.   */ -struct snd_soc_dai { +struct snd_soc_dai_driver {  	/* DAI description */ -	char *name; +	const char *name;  	unsigned int id;  	int ac97_control; -	struct device *dev; -	void *ac97_pdata;	/* platform_data for the ac97 codec */ - -	/* DAI callbacks */ -	int (*probe)(struct platform_device *pdev, -		     struct snd_soc_dai *dai); -	void (*remove)(struct platform_device *pdev, -		       struct snd_soc_dai *dai); +	/* DAI driver callbacks */ +	int (*probe)(struct snd_soc_dai *dai); +	int (*remove)(struct snd_soc_dai *dai);  	int (*suspend)(struct snd_soc_dai *dai);  	int (*resume)(struct snd_soc_dai *dai); @@ -219,26 +211,51 @@ struct snd_soc_dai {  	struct snd_soc_pcm_stream capture;  	struct snd_soc_pcm_stream playback;  	unsigned int symmetric_rates:1; +}; + +/* + * Digital Audio Interface runtime data. + * + * Holds runtime data for a DAI. + */ +struct snd_soc_dai { +	const char *name; +	int id; +	struct device *dev; +	void *ac97_pdata;	/* platform_data for the ac97 codec */ + +	/* driver ops */ +	struct snd_soc_dai_driver *driver;  	/* DAI runtime info */ -	struct snd_soc_codec *codec; +	unsigned int capture_active:1;		/* stream is in use */ +	unsigned int playback_active:1;		/* stream is in use */ +	unsigned int symmetric_rates:1; +	struct snd_pcm_runtime *runtime;  	unsigned int active;  	unsigned char pop_wait:1; +	unsigned char probed:1; -	/* DAI private data */ -	void *private_data; +	/* DAI DMA data */ +	void *playback_dma_data; +	void *capture_dma_data; -	/* parent platform */ -	struct snd_soc_platform *platform; +	/* parent platform/codec */ +	union { +		struct snd_soc_platform *platform; +		struct snd_soc_codec *codec; +	}; +	struct snd_soc_card *card;  	struct list_head list; +	struct list_head card_list;  };  static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,  					     const struct snd_pcm_substream *ss)  {  	return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -		dai->playback.dma_data : dai->capture.dma_data; +		dai->playback_dma_data : dai->capture_dma_data;  }  static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, @@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,  					    void *data)  {  	if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) -		dai->playback.dma_data = data; +		dai->playback_dma_data = data;  	else -		dai->capture.dma_data = data; +		dai->capture_dma_data = data; +} + +static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai, +		void *data) +{ +	dev_set_drvdata(dai->dev, data); +} + +static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai) +{ +	return dev_get_drvdata(dai->dev);  }  #endif diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c5d9987bc897..c4a445651ca0 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -322,14 +322,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,  /* dapm path setup */  int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); -void snd_soc_dapm_free(struct snd_soc_device *socdev); +void snd_soc_dapm_free(struct snd_soc_codec *codec);  int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,  			    const struct snd_soc_dapm_route *route, int num);  /* dapm events */ -int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, -	int event); -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); +int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, +	const char *stream, int event); +void snd_soc_dapm_shutdown(struct snd_soc_card *card);  /* dapm sys fs - used by the core */  int snd_soc_dapm_sys_add(struct device *dev); diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h deleted file mode 100644 index a064e1934a56..000000000000 --- a/include/sound/soc-of-simple.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * OF helpers for ALSA SoC - * - * Copyright (C) 2008, Secret Lab Technologies Ltd. - */ - -#ifndef _INCLUDE_SOC_OF_H_ -#define _INCLUDE_SOC_OF_H_ - -#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE) - -#include <linux/of.h> -#include <sound/soc.h> - -int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, -			      void *codec_data, struct snd_soc_dai *dai, -			      struct device_node *node); - -int of_snd_soc_register_platform(struct snd_soc_platform *platform, -				 struct device_node *node, -				 struct snd_soc_dai *cpu_dai); - -#endif - -#endif /* _INCLUDE_SOC_OF_H_ */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 65e9d03ed4f5..d31e8b7b2d5e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -228,13 +228,17 @@ struct snd_soc_ops;  struct snd_soc_dai_mode;  struct snd_soc_pcm_runtime;  struct snd_soc_dai; +struct snd_soc_dai_driver;  struct snd_soc_platform;  struct snd_soc_dai_link; +struct snd_soc_platform_driver;  struct snd_soc_codec; +struct snd_soc_codec_driver;  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 @@ -249,19 +253,18 @@ enum snd_soc_control_type {  	SND_SOC_SPI,  }; -int snd_soc_register_platform(struct snd_soc_platform *platform); -void snd_soc_unregister_platform(struct snd_soc_platform *platform); -int snd_soc_register_codec(struct snd_soc_codec *codec); -void snd_soc_unregister_codec(struct snd_soc_codec *codec); +int snd_soc_register_platform(struct device *dev, +		struct snd_soc_platform_driver *platform_drv); +void snd_soc_unregister_platform(struct device *dev); +int snd_soc_register_codec(struct device *dev, +		struct snd_soc_codec_driver *codec_drv, +		struct snd_soc_dai_driver *dai_drv, int num_dai); +void snd_soc_unregister_codec(struct device *dev);  int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);  int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,  			       int addr_bits, int data_bits,  			       enum snd_soc_control_type control); -/* pcm <-> DAI connect */ -void snd_soc_free_pcms(struct snd_soc_device *socdev); -int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); -  /* Utility functions to get clock rates from various things */  int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);  int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); @@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,  	const struct snd_pcm_hardware *hw);  /* Jack reporting */ -int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, +int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,  		     struct snd_soc_jack *jack);  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, @@ -390,7 +393,7 @@ struct snd_soc_jack_gpio {  struct snd_soc_jack {  	struct snd_jack *jack; -	struct snd_soc_card *card; +	struct snd_soc_codec *codec;  	struct list_head pins;  	int status;  	struct blocking_notifier_head notifier; @@ -398,15 +401,13 @@ struct snd_soc_jack {  /* SoC PCM stream information */  struct snd_soc_pcm_stream { -	char *stream_name; +	const char *stream_name;  	u64 formats;			/* SNDRV_PCM_FMTBIT_* */  	unsigned int rates;		/* SNDRV_PCM_RATE_* */  	unsigned int rate_min;		/* min rate */  	unsigned int rate_max;		/* max rate */  	unsigned int channels_min;	/* min channels */  	unsigned int channels_max;	/* max channels */ -	unsigned int active;		/* stream is in use */ -	void *dma_data;			/* used by platform code */  };  /* SoC audio ops */ @@ -419,44 +420,35 @@ struct snd_soc_ops {  	int (*trigger)(struct snd_pcm_substream *, int);  }; -/* SoC Audio Codec */ +/* SoC Audio Codec device */  struct snd_soc_codec { -	char *name; -	struct module *owner; -	struct mutex mutex; +	const char *name; +	int id;  	struct device *dev; -	struct snd_soc_device *socdev; +	struct snd_soc_codec_driver *driver; +	struct mutex mutex; +	struct snd_soc_card *card;  	struct list_head list; - -	/* callbacks */ -	int (*set_bias_level)(struct snd_soc_codec *, -			      enum snd_soc_bias_level level); +	struct list_head card_list; +	int num_dai;  	/* runtime */ -	struct snd_card *card;  	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */  	unsigned int active; -	unsigned int pcm_devs; -	void *drvdata; +	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ +	unsigned int cache_only:1;  /* Suppress writes to hardware */ +	unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ +	unsigned int suspended:1; /* Codec is in suspend PM state */ +	unsigned int probed:1; /* Codec has been probed */ +	unsigned int ac97_registered:1; /* Codec has been AC97 registered */ +	unsigned int sysfs_registered:1; /* codec has been sysfs registered */  	/* codec IO */  	void *control_data; /* codec control (i2c/3wire) data */ -	unsigned int (*read)(struct snd_soc_codec *, unsigned int); -	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); -	int (*display_register)(struct snd_soc_codec *, char *, -				size_t, unsigned int); -	int (*volatile_register)(unsigned int); -	int (*readable_register)(unsigned int);  	hw_write_t hw_write;  	unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);  	void *reg_cache; -	short reg_cache_size; -	short reg_cache_step; - -	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ -	unsigned int cache_only:1;  /* Suppress writes to hardware */ -	unsigned int cache_sync:1; /* Cache needs to be synced to hardware */  	/* dapm */  	u32 pop_time; @@ -466,10 +458,6 @@ struct snd_soc_codec {  	enum snd_soc_bias_level suspend_bias_level;  	struct delayed_work delayed_work; -	/* codec DAI's */ -	struct snd_soc_dai *dai; -	unsigned int num_dai; -  #ifdef CONFIG_DEBUG_FS  	struct dentry *debugfs_codec_root;  	struct dentry *debugfs_reg; @@ -478,23 +466,40 @@ struct snd_soc_codec {  #endif  }; -/* codec device */ -struct snd_soc_codec_device { -	int (*probe)(struct platform_device *pdev); -	int (*remove)(struct platform_device *pdev); -	int (*suspend)(struct platform_device *pdev, pm_message_t state); -	int (*resume)(struct platform_device *pdev); +/* codec driver */ +struct snd_soc_codec_driver { + +	/* driver ops */ +	int (*probe)(struct snd_soc_codec *); +	int (*remove)(struct snd_soc_codec *); +	int (*suspend)(struct snd_soc_codec *, +			pm_message_t state); +	int (*resume)(struct snd_soc_codec *); + +	/* codec IO */ +	unsigned int (*read)(struct snd_soc_codec *, unsigned int); +	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); +	int (*display_register)(struct snd_soc_codec *, char *, +				size_t, unsigned int); +	int (*volatile_register)(unsigned int); +	int (*readable_register)(unsigned int); +	short reg_cache_size; +	short reg_cache_step; +	short reg_word_size; +	const void *reg_cache_default; + +	/* codec bias level */ +	int (*set_bias_level)(struct snd_soc_codec *, +			      enum snd_soc_bias_level level);  };  /* SoC platform interface */ -struct snd_soc_platform { -	char *name; -	struct list_head list; +struct snd_soc_platform_driver { -	int (*probe)(struct platform_device *pdev); -	int (*remove)(struct platform_device *pdev); -	int (*suspend)(struct snd_soc_dai_link *dai_link); -	int (*resume)(struct snd_soc_dai_link *dai_link); +	int (*probe)(struct snd_soc_platform *); +	int (*remove)(struct snd_soc_platform *); +	int (*suspend)(struct snd_soc_dai *dai); +	int (*resume)(struct snd_soc_dai *dai);  	/* pcm creation and destruction */  	int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, @@ -509,23 +514,31 @@ struct snd_soc_platform {  		struct snd_soc_dai *);  	/* platform stream ops */ -	struct snd_pcm_ops *pcm_ops; +	struct snd_pcm_ops *ops;  }; -/* SoC machine DAI configuration, glues a codec and cpu DAI together */ -struct snd_soc_dai_link  { -	char *name;			/* Codec name */ -	char *stream_name;		/* Stream name */ +struct snd_soc_platform { +	const char *name; +	int id; +	struct device *dev; +	struct snd_soc_platform_driver *driver; -	/* DAI */ -	struct snd_soc_dai *codec_dai; -	struct snd_soc_dai *cpu_dai; +	unsigned int suspended:1; /* platform is suspended */ +	unsigned int probed:1; -	/* machine stream operations */ -	struct snd_soc_ops *ops; +	struct snd_soc_card *card; +	struct list_head list; +	struct list_head card_list; +}; -	/* codec/machine specific init - e.g. add machine controls */ -	int (*init)(struct snd_soc_codec *codec); +struct snd_soc_dai_link { +	/* config - must be set by machine driver */ +	const char *name;			/* Codec name */ +	const char *stream_name;		/* Stream name */ +	const char *codec_name;		/* for multi-codec */ +	const char *platform_name;	/* for multi-platform */ +	const char *cpu_dai_name; +	const char *codec_dai_name;  	/* Keep DAI active over suspend */  	unsigned int ignore_suspend:1; @@ -533,21 +546,24 @@ struct snd_soc_dai_link  {  	/* Symmetry requirements */  	unsigned int symmetric_rates:1; -	/* Symmetry data - only valid if symmetry is being enforced */ -	unsigned int rate; +	/* codec/machine specific init - e.g. add machine controls */ +	int (*init)(struct snd_soc_pcm_runtime *rtd); -	/* DAI pcm */ -	struct snd_pcm *pcm; +	/* machine stream operations */ +	struct snd_soc_ops *ops;  };  /* SoC card */  struct snd_soc_card { -	char *name; +	const char *name;  	struct device *dev; +	struct snd_card *snd_card; +	struct module *owner;  	struct list_head list; +	struct mutex mutex; -	int instantiated; +	bool instantiated;  	int (*probe)(struct platform_device *pdev);  	int (*remove)(struct platform_device *pdev); @@ -568,28 +584,38 @@ struct snd_soc_card {  	/* CPU <--> Codec DAI links  */  	struct snd_soc_dai_link *dai_link;  	int num_links; +	struct snd_soc_pcm_runtime *rtd; +	int num_rtd; -	struct snd_soc_device *socdev; - -	struct snd_soc_codec *codec; - -	struct snd_soc_platform *platform; -	struct delayed_work delayed_work;  	struct work_struct deferred_resume_work; + +	/* lists of probed devices belonging to this card */ +	struct list_head codec_dev_list; +	struct list_head platform_dev_list; +	struct list_head dai_dev_list;  }; -/* SoC Device - the audio subsystem */ -struct snd_soc_device { -	struct device *dev; +/* SoC machine DAI configuration, glues a codec and cpu DAI together */ +struct snd_soc_pcm_runtime  { +	struct device dev;  	struct snd_soc_card *card; -	struct snd_soc_codec_device *codec_dev; -	void *codec_data; -}; +	struct snd_soc_dai_link *dai_link; + +	unsigned int complete:1; +	unsigned int dev_registered:1; -/* runtime channel data */ -struct snd_soc_pcm_runtime { -	struct snd_soc_dai_link *dai; -	struct snd_soc_device *socdev; +	/* Symmetry data - only valid if symmetry is being enforced */ +	unsigned int rate; +	long pmdown_time; + +	/* runtime devices */ +	struct snd_pcm *pcm; +	struct snd_soc_codec *codec; +	struct snd_soc_platform *platform; +	struct snd_soc_dai *codec_dai; +	struct snd_soc_dai *cpu_dai; + +	struct delayed_work delayed_work;  };  /* mixer control */ @@ -615,24 +641,48 @@ struct soc_enum {  static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,  					unsigned int reg)  { -	return codec->read(codec, reg); +	return codec->driver->read(codec, reg);  }  static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,  					 unsigned int reg, unsigned int val)  { -	return codec->write(codec, reg, val); +	return codec->driver->write(codec, reg, val);  } +/* device driver data */ +  static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, -					     void *data) +		void *data)  { -	codec->drvdata = data; +	dev_set_drvdata(codec->dev, data);  }  static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)  { -	return codec->drvdata; +	return dev_get_drvdata(codec->dev); +} + +static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform, +		void *data) +{ +	dev_set_drvdata(platform->dev, data); +} + +static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform) +{ +	return dev_get_drvdata(platform->dev); +} + +static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, +		void *data) +{ +	dev_set_drvdata(&rtd->dev, data); +} + +static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd) +{ +	return dev_get_drvdata(&rtd->dev);  }  #include <sound/soc-dai.h> diff --git a/include/sound/tlv320aic3x.h b/include/sound/tlv320aic3x.h index b1a5f34e5cfa..99e0308bf2c2 100644 --- a/include/sound/tlv320aic3x.h +++ b/include/sound/tlv320aic3x.h @@ -10,8 +10,49 @@  #ifndef __TLV320AIC3x_H__  #define __TLV320AIC3x_H__ +/* GPIO API */ +enum { +	AIC3X_GPIO1_FUNC_DISABLED		= 0, +	AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC	= 1, +	AIC3X_GPIO1_FUNC_CLOCK_MUX		= 2, +	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2		= 3, +	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4		= 4, +	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8		= 5, +	AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ	= 6, +	AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ		= 7, +	AIC3X_GPIO1_FUNC_INPUT			= 8, +	AIC3X_GPIO1_FUNC_OUTPUT			= 9, +	AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK	= 10, +	AIC3X_GPIO1_FUNC_AUDIO_WORDCLK		= 11, +	AIC3X_GPIO1_FUNC_BUTTON_IRQ		= 12, +	AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ	= 13, +	AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ	= 14, +	AIC3X_GPIO1_FUNC_ALL_IRQ		= 16 +}; + +enum { +	AIC3X_GPIO2_FUNC_DISABLED		= 0, +	AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ	= 2, +	AIC3X_GPIO2_FUNC_INPUT			= 3, +	AIC3X_GPIO2_FUNC_OUTPUT			= 4, +	AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT	= 5, +	AIC3X_GPIO2_FUNC_AUDIO_BITCLK		= 8, +	AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, +	AIC3X_GPIO2_FUNC_ALL_IRQ		= 10, +	AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, +	AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, +	AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ	= 13, +	AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ		= 14, +	AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ	= 15 +}; + +struct aic3x_setup_data { +	unsigned int gpio_func[2]; +}; +  struct aic3x_pdata {  	int gpio_reset; /* < 0 if not used */ +	struct aic3x_setup_data *setup;  }; -#endif
\ No newline at end of file +#endif diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index dc5249fba85c..d0e75323ec19 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,  	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);  	runtime->dma_bytes = params_buffer_bytes(params); -	prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	prtd->params->dma_intr_handler = atmel_pcm_dma_irq;  	prtd->dma_buffer = runtime->dma_addr; @@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = 0xffffffff; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = atmel_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		pr_debug("at32-pcm:"  				"Allocating PCM capture DMA buffer\n");  		ret = atmel_pcm_preallocate_dma_buffer(pcm, @@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)  }  #ifdef CONFIG_PM -static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) +static int atmel_pcm_suspend(struct snd_soc_dai *dai)  { -	struct snd_pcm *pcm = dai_link->pcm; -	struct snd_pcm_str *stream = &pcm->streams[0]; -	struct snd_pcm_substream *substream = stream->substream; -	struct snd_pcm_runtime *runtime = substream->runtime; +	struct snd_pcm_runtime *runtime = dai->runtime;  	struct atmel_runtime_data *prtd;  	struct atmel_pcm_dma_params *params; @@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)  	return 0;  } -static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) +static int atmel_pcm_resume(struct snd_soc_dai *dai)  { -	struct snd_pcm *pcm = dai_link->pcm; -	struct snd_pcm_str *stream = &pcm->streams[0]; -	struct snd_pcm_substream *substream = stream->substream; -	struct snd_pcm_runtime *runtime = substream->runtime; +	struct snd_pcm_runtime *runtime = dai->runtime;  	struct atmel_runtime_data *prtd;  	struct atmel_pcm_dma_params *params; @@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)  #define atmel_pcm_resume	NULL  #endif -struct snd_soc_platform atmel_soc_platform = { -	.name		= "atmel-audio", -	.pcm_ops 	= &atmel_pcm_ops, +static struct snd_soc_platform_driver atmel_soc_platform = { +	.ops		= &atmel_pcm_ops,  	.pcm_new	= atmel_pcm_new,  	.pcm_free	= atmel_pcm_free_dma_buffers,  	.suspend	= atmel_pcm_suspend,  	.resume		= atmel_pcm_resume,  }; -EXPORT_SYMBOL_GPL(atmel_soc_platform); -static int __init atmel_pcm_modinit(void) +static int __devinit atmel_soc_platform_probe(struct platform_device *pdev) +{ +	return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform); +} + +static int __devexit atmel_soc_platform_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver atmel_pcm_driver = { +	.driver = { +			.name = "atmel-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = atmel_soc_platform_probe, +	.remove = __devexit_p(atmel_soc_platform_remove), +}; + +static int __init snd_atmel_pcm_init(void)  { -	return snd_soc_register_platform(&atmel_soc_platform); +	return platform_driver_register(&atmel_pcm_driver);  } -module_init(atmel_pcm_modinit); +module_init(snd_atmel_pcm_init); -static void __exit atmel_pcm_modexit(void) +static void __exit snd_atmel_pcm_exit(void)  { -	snd_soc_unregister_platform(&atmel_soc_platform); +	platform_driver_unregister(&atmel_pcm_driver);  } -module_exit(atmel_pcm_modexit); +module_exit(snd_atmel_pcm_exit);  MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");  MODULE_DESCRIPTION("Atmel PCM module"); diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index ec9b2824b663..2597329302e7 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h @@ -74,9 +74,6 @@ struct atmel_pcm_dma_params {  	void (*dma_intr_handler)(u32, struct snd_pcm_substream *);  }; -extern struct snd_soc_platform atmel_soc_platform; - -  /*   * SSC register access (since ssc_writel() / ssc_readl() require literal name)   */ diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c85844d4845b..eabf66af12cd 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)  static int atmel_ssc_startup(struct snd_pcm_substream *substream,  			     struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); -	struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; +	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];  	int dir_mask;  	pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", @@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,  static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,  			       struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); -	struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; +	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];  	struct atmel_pcm_dma_params *dma_params;  	int dir, dir_mask; @@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); -	int id = rtd->dai->cpu_dai->id; +	int id = dai->id;  	struct atmel_ssc_info *ssc_p = &ssc_info[id];  	struct atmel_pcm_dma_params *dma_params;  	int dir, channels, bits; @@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,  	 * function.  It should not be used for other purposes  	 * as it is common to all substreams.  	 */ -	snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params); +	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);  	channels = params_channels(params); @@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,  static int atmel_ssc_prepare(struct snd_pcm_substream *substream,  			     struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); -	struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; +	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];  	struct atmel_pcm_dma_params *dma_params;  	int dir; @@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)  #  define atmel_ssc_resume	NULL  #endif /* CONFIG_PM */ +static int atmel_ssc_probe(struct snd_soc_dai *dai) +{ +	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; +	int ret = 0; + +	snd_soc_dai_set_drvdata(dai, ssc_p); + +	/* +	 * Request SSC device +	 */ +	ssc_p->ssc = ssc_request(dai->id); +	if (IS_ERR(ssc_p->ssc)) { +		printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id); +		ret = PTR_ERR(ssc_p->ssc); +	} + +	return ret; +} + +static int atmel_ssc_remove(struct snd_soc_dai *dai) +{ +	struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai); + +	ssc_free(ssc_p->ssc); +	return 0; +}  #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) @@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = {  	.set_clkdiv	= atmel_ssc_set_dai_clkdiv,  }; -struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { -	{	.name = "atmel-ssc0", -		.id = 0, +static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { +	{ +		.name = "atmel-ssc-dai.0", +		.probe = atmel_ssc_probe, +		.remove = atmel_ssc_remove,  		.suspend = atmel_ssc_suspend,  		.resume = atmel_ssc_resume,  		.playback = { @@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {  			.rates = ATMEL_SSC_RATES,  			.formats = ATMEL_SSC_FORMATS,},  		.ops = &atmel_ssc_dai_ops, -		.private_data = &ssc_info[0],  	},  #if NUM_SSC_DEVICES == 3 -	{	.name = "atmel-ssc1", -		.id = 1, +	{ +		.name = "atmel-ssc-dai.1", +		.probe = atmel_ssc_probe, +		.remove = atmel_ssc_remove,  		.suspend = atmel_ssc_suspend,  		.resume = atmel_ssc_resume,  		.playback = { @@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {  			.rates = ATMEL_SSC_RATES,  			.formats = ATMEL_SSC_FORMATS,},  		.ops = &atmel_ssc_dai_ops, -		.private_data = &ssc_info[1],  	}, -	{	.name = "atmel-ssc2", -		.id = 2, +	{ +		.name = "atmel-ssc-dai.2", +		.probe = atmel_ssc_probe, +		.remove = atmel_ssc_remove,  		.suspend = atmel_ssc_suspend,  		.resume = atmel_ssc_resume,  		.playback = { @@ -756,23 +783,43 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {  			.rates = ATMEL_SSC_RATES,  			.formats = ATMEL_SSC_FORMATS,},  		.ops = &atmel_ssc_dai_ops, -		.private_data = &ssc_info[2],  	},  #endif  }; -EXPORT_SYMBOL_GPL(atmel_ssc_dai); -static int __init atmel_ssc_modinit(void) +static __devinit int asoc_ssc_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dais(&pdev->dev, atmel_ssc_dai, +			ARRAY_SIZE(atmel_ssc_dai)); +} + +static int __devexit asoc_ssc_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(atmel_ssc_dai)); +	return 0; +} + +static struct platform_driver asoc_ssc_driver = { +	.driver = { +			.name = "atmel-ssc-dai", +			.owner = THIS_MODULE, +	}, + +	.probe = asoc_ssc_probe, +	.remove = __devexit_p(asoc_ssc_remove), +}; + +static int __init snd_atmel_ssc_init(void)  { -	return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); +	return platform_driver_register(&asoc_ssc_driver);  } -module_init(atmel_ssc_modinit); +module_init(snd_atmel_ssc_init); -static void __exit atmel_ssc_modexit(void) +static void __exit snd_atmel_ssc_exit(void)  { -	snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); +	platform_driver_unregister(&asoc_ssc_driver);  } -module_exit(atmel_ssc_modexit); +module_exit(snd_atmel_ssc_exit);  /* Module information */  MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h index 391135f9c6c1..392a46953112 100644 --- a/sound/soc/atmel/atmel_ssc_dai.h +++ b/sound/soc/atmel/atmel_ssc_dai.h @@ -116,6 +116,5 @@ struct atmel_ssc_info {  	struct atmel_pcm_dma_params *dma_params[2];  	struct atmel_ssc_state ssc_state;  }; -extern struct snd_soc_dai atmel_ssc_dai[];  #endif /* _AT91_SSC_DAI_H */ diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 9df4c68ef000..5f4e59f4461c 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c @@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(  	struct snd_pcm_hw_params *params,  	struct snd_soc_dai *cpu_dai)  { -	struct at32_ssc_info *ssc_p = cpu_dai->private_data; +	struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssc_device *ssc = ssc_p->ssc;  	struct ssc_clock_data cd;  	unsigned int rate, width_bits, channels; @@ -131,9 +131,9 @@ static int playpaq_wm8510_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 at32_ssc_info *ssc_p = cpu_dai->private_data; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssc_device *ssc = ssc_p->ssc;  	unsigned int pll_out = 0, bclk = 0, mclk_div = 0;  	int ret; @@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = { -static int playpaq_wm8510_init(struct snd_soc_codec *codec) +static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int i;  	/* @@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)  	/* Make CSB show PLL rate */ -	snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV, +	snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,  				       WM8510_OPCLKDIV_1 | 4);  	return 0; @@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link playpaq_wm8510_dai = {  	.name = "WM8510",  	.stream_name = "WM8510 PCM", -	.cpu_dai = &at32_ssc_dai[0], -	.codec_dai = &wm8510_dai, +	.cpu_dai_name= "atmel-ssc-dai.0", +	.platform_name = "atmel-pcm-audio", +	.codec_name = "wm8510-codec.0-0x1a", +	.codec_dai_name = "wm8510-hifi",  	.init = playpaq_wm8510_init,  	.ops = &playpaq_wm8510_ops,  }; @@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {  static struct snd_soc_card snd_soc_playpaq = {  	.name = "LRS_PlayPaq_WM8510", -	.platform = &at32_soc_platform,  	.dai_link = &playpaq_wm8510_dai,  	.num_links = 1,  }; - - -static struct wm8510_setup_data playpaq_wm8510_setup = { -	.i2c_bus = 0, -	.i2c_address = 0x1a, -}; - - - -static struct snd_soc_device playpaq_wm8510_snd_devdata = { -	.card = &snd_soc_playpaq, -	.codec_dev = &soc_codec_dev_wm8510, -	.codec_data = &playpaq_wm8510_setup, -}; -  static struct platform_device *playpaq_snd_device;  static int __init playpaq_asoc_init(void)  {  	int ret = 0; -	struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; -	struct ssc_device *ssc = NULL; - - -	/* -	 * Request SSC device -	 */ -	ssc = ssc_request(0); -	if (IS_ERR(ssc)) { -		ret = PTR_ERR(ssc); -		goto err_ssc; -	} -	ssc_p->ssc = ssc; -  	/*  	 * Configure MCLK for WM8510 @@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void)  		goto err_device_alloc;  	} -	platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata); -	playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev; +	platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);  	ret = platform_device_add(playpaq_snd_device);  	if (ret) { @@ -468,25 +440,12 @@ err_pll0:  		clk_put(_gclk0);  		_gclk0 = NULL;  	} -err_gclk0: -	ssc_free(ssc); -err_ssc:  	return ret;  }  static void __exit playpaq_asoc_exit(void)  { -	struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data; -	struct ssc_device *ssc; - -	if (ssc_p != NULL) { -		ssc = ssc_p->ssc; -		if (ssc != NULL) -			ssc_free(ssc); -		ssc_p->ssc = NULL; -	} -  	if (_gclk0 != NULL) {  		clk_put(_gclk0);  		_gclk0 = NULL; diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index e028744c32ce..66a6f1879689 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -69,8 +69,8 @@ static int at91sam9g20ek_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* set codec DAI configuration */ @@ -136,9 +136,10 @@ static const struct snd_soc_dapm_route intercon[] = {  /*   * Logic for a wm8731 as connected on a at91sam9g20ek board.   */ -static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) +static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)  { -	struct snd_soc_dai *codec_dai = &codec->dai[0]; +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	int ret;  	printk(KERN_DEBUG @@ -179,31 +180,25 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link at91sam9g20ek_dai = {  	.name = "WM8731",  	.stream_name = "WM8731 PCM", -	.cpu_dai = &atmel_ssc_dai[0], -	.codec_dai = &wm8731_dai, +	.cpu_dai_name = "atmel-ssc-dai.0", +	.codec_dai_name = "wm8731-hifi",  	.init = at91sam9g20ek_wm8731_init, +	.platform_name = "atmel_pcm-audio", +	.codec_name = "wm8731-codec.0-001a",  	.ops = &at91sam9g20ek_ops,  };  static struct snd_soc_card snd_soc_at91sam9g20ek = {  	.name = "AT91SAMG20-EK", -	.platform = &atmel_soc_platform,  	.dai_link = &at91sam9g20ek_dai,  	.num_links = 1,  	.set_bias_level = at91sam9g20ek_set_bias_level,  }; -static struct snd_soc_device at91sam9g20ek_snd_devdata = { -	.card = &snd_soc_at91sam9g20ek, -	.codec_dev = &soc_codec_dev_wm8731, -}; -  static struct platform_device *at91sam9g20ek_snd_device;  static int __init at91sam9g20ek_init(void)  { -	struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; -	struct ssc_device *ssc = NULL;  	struct clk *pllb;  	int ret; @@ -235,18 +230,6 @@ static int __init at91sam9g20ek_init(void)  	clk_set_rate(mclk, MCLK_RATE); -	/* -	 * Request SSC device -	 */ -	ssc = ssc_request(0); -	if (IS_ERR(ssc)) { -		printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); -		ret = PTR_ERR(ssc); -		ssc = NULL; -		goto err_ssc; -	} -	ssc_p->ssc = ssc; -  	at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);  	if (!at91sam9g20ek_snd_device) {  		printk(KERN_ERR "ASoC: Platform device allocation failed\n"); @@ -254,8 +237,7 @@ static int __init at91sam9g20ek_init(void)  	}  	platform_set_drvdata(at91sam9g20ek_snd_device, -			&at91sam9g20ek_snd_devdata); -	at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; +			&snd_soc_at91sam9g20ek);  	ret = platform_device_add(at91sam9g20ek_snd_device);  	if (ret) { @@ -265,9 +247,6 @@ static int __init at91sam9g20ek_init(void)  	return ret; -err_ssc: -	ssc_free(ssc); -	ssc_p->ssc = NULL;  err_mclk:  	clk_put(mclk);  	mclk = NULL; @@ -277,16 +256,6 @@ err:  static void __exit at91sam9g20ek_exit(void)  { -	struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; -	struct ssc_device *ssc; - -	if (ssc_p != NULL) { -		ssc = ssc_p->ssc; -		if (ssc != NULL) -			ssc_free(ssc); -		ssc_p->ssc = NULL; -	} -  	platform_device_unregister(at91sam9g20ek_snd_device);  	at91sam9g20ek_snd_device = NULL;  	clk_put(mclk); diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index 23349de27313..e3d283561c19 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c @@ -46,8 +46,8 @@ static int afeb9260_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int err;  	/* Set codec DAI configuration */ @@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MICIN", NULL, "Mic Jack"},  }; -static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) +static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	/* Add afeb9260 specific widgets */  	snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, @@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link afeb9260_dai = {  	.name = "TLV320AIC23",  	.stream_name = "AIC23", -	.cpu_dai = &atmel_ssc_dai[0], -	.codec_dai = &tlv320aic23_dai, +	.cpu_dai_name = "atmel-ssc-dai.0", +	.codec_dai_name = "tlv320aic23-hifi", +	.platform_name = "atmel_pcm-audio", +	.codec_name = "tlv320aic23-codec.0-0x1a",  	.init = afeb9260_tlv320aic23_init,  	.ops = &afeb9260_ops,  }; @@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_machine_afeb9260 = {  	.name = "AFEB9260", -	.platform = &atmel_soc_platform,  	.dai_link = &afeb9260_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device afeb9260_snd_devdata = { -	.card = &snd_soc_machine_afeb9260, -	.codec_dev = &soc_codec_dev_tlv320aic23, -}; -  static struct platform_device *afeb9260_snd_device;  static int __init afeb9260_soc_init(void)  {  	int err;  	struct device *dev; -	struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data; -	struct ssc_device *ssc = NULL;  	if (!(machine_is_afeb9260()))  		return -ENODEV; -	ssc = ssc_request(0); -	if (IS_ERR(ssc)) { -		printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); -		err = PTR_ERR(ssc); -		ssc = NULL; -		goto err_ssc; -	} -	ssc_p->ssc = ssc;  	afeb9260_snd_device = platform_device_alloc("soc-audio", -1);  	if (!afeb9260_snd_device) { @@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata); -	afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev; +	platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);  	err = platform_device_add(afeb9260_snd_device);  	if (err)  		goto err1; @@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void)  err1:  	platform_device_del(afeb9260_snd_device);  	platform_device_put(afeb9260_snd_device); -err_ssc:  	return err; -  }  static void __exit afeb9260_soc_exit(void) diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index cdf7be1b9b91..8780c90107fc 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -19,7 +19,6 @@  #include <asm/mach-au1x00/au1xxx_dbdma.h>  #include <asm/mach-db1x00/bcsr.h> -#include "../codecs/ac97.h"  #include "../codecs/wm8731.h"  #include "psc.h" @@ -28,20 +27,16 @@  static struct snd_soc_dai_link db1200_ac97_dai = {  	.name		= "AC97",  	.stream_name	= "AC97 HiFi", -	.cpu_dai	= &au1xpsc_ac97_dai, -	.codec_dai	= &ac97_dai, +	.cpu_dai_name	= "au1xpsc-ac97", +	.codec_dai_name	= "ac97-hifi", +	.platform_name	=  "au1xpsc-pcm-audio", +	.codec_name	= "ac97-codec",  };  static struct snd_soc_card db1200_ac97_machine = {  	.name		= "DB1200_AC97",  	.dai_link	= &db1200_ac97_dai,  	.num_links	= 1, -	.platform	= &au1xpsc_soc_platform, -}; - -static struct snd_soc_device db1200_ac97_devdata = { -	.card		= &db1200_ac97_machine, -	.codec_dev	= &soc_codec_dev_ac97,  };  /*-------------------------  I2S PART  ---------------------------*/ @@ -49,8 +44,8 @@ static struct snd_soc_device db1200_ac97_devdata = {  static int db1200_i2s_startup(struct snd_pcm_substream *substream)  {  	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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* WM8731 has its own 12MHz crystal */ @@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = {  static struct snd_soc_dai_link db1200_i2s_dai = {  	.name		= "WM8731",  	.stream_name	= "WM8731 PCM", -	.cpu_dai	= &au1xpsc_i2s_dai, -	.codec_dai	= &wm8731_dai, +	.cpu_dai_name	= "au1xpsc", +	.codec_dai_name	= "wm8731-hifi" +	.platform_name	= "au1xpsc-pcm-audio", +	.codec_name	= "wm8731-codec.0-001a",  	.ops		= &db1200_i2s_wm8731_ops,  }; @@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = {  	.name		= "DB1200_I2S",  	.dai_link	= &db1200_i2s_dai,  	.num_links	= 1, -	.platform	= &au1xpsc_soc_platform, -}; - -static struct snd_soc_device db1200_i2s_devdata = { -	.card		= &db1200_i2s_machine, -	.codec_dev	= &soc_codec_dev_wm8731,  };  /*-------------------------  COMMON PART  ---------------------------*/ @@ -112,12 +103,10 @@ static int __init db1200_audio_load(void)  	/* DB1200 board setup set PSC1MUX to preferred audio device */  	if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) -		platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata); +		platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);  	else -		platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata); +		platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine); -	db1200_ac97_devdata.dev = &db1200_asoc_dev->dev; -	db1200_i2s_devdata.dev = &db1200_asoc_dev->dev;  	ret = platform_device_add(db1200_asoc_dev);  	if (ret) { diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 6d9f4c624949..00fdb9cbfc2d 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -329,7 +329,7 @@ static int au1xpsc_pcm_new(struct snd_card *card,  	return 0;  } -static int au1xpsc_pcm_probe(struct platform_device *pdev) +static int au1xpsc_pcm_probe(struct snd_soc_platform *platform)  {  	if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])  		return -ENODEV; @@ -337,17 +337,10 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)  	return 0;  } -static int au1xpsc_pcm_remove(struct platform_device *pdev) -{ -	return 0; -} -  /* au1xpsc audio platform */ -struct snd_soc_platform au1xpsc_soc_platform = { -	.name		= "au1xpsc-pcm-dbdma", +struct snd_soc_platform_driver au1xpsc_soc_platform = {  	.probe		= au1xpsc_pcm_probe, -	.remove		= au1xpsc_pcm_remove, -	.pcm_ops 	= &au1xpsc_pcm_ops, +	.ops		= &au1xpsc_pcm_ops,  	.pcm_new	= au1xpsc_pcm_new,  	.pcm_free	= au1xpsc_pcm_free_dma_buffers,  }; @@ -387,7 +380,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)  	}  	(au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; -	ret = snd_soc_register_platform(&au1xpsc_soc_platform); +	ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);  	if (!ret)  		return ret; @@ -404,7 +397,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)  {  	int i; -	snd_soc_unregister_platform(&au1xpsc_soc_platform); +	snd_soc_unregister_platform(&pdev->dev);  	for (i = 0; i < 2; i++) {  		if (au1xpsc_audio_pcmdma[i]) { @@ -419,7 +412,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)  static struct platform_driver au1xpsc_pcm_driver = {  	.driver	= { -		.name	= "au1xpsc-pcm", +		.name	= "au1xpsc-pcm-audio",  		.owner	= THIS_MODULE,  	},  	.probe		= au1xpsc_pcm_drvprobe, diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index d14a5a91a465..6a9516cbe424 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -315,27 +315,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,  	return ret;  } -static int au1xpsc_ac97_probe(struct platform_device *pdev, -			      struct snd_soc_dai *dai) +static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)  {  	return au1xpsc_ac97_workdata ? 0 : -ENODEV;  } -static void au1xpsc_ac97_remove(struct platform_device *pdev, -				struct snd_soc_dai *dai) -{ -} -  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", +struct snd_soc_dai_driver au1xpsc_ac97_dai = {  	.ac97_control		= 1,  	.probe			= au1xpsc_ac97_probe, -	.remove			= au1xpsc_ac97_remove,  	.playback = {  		.rates		= AC97_RATES,  		.formats	= AC97_FMTS, @@ -395,7 +387,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)  	au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));  	au_sync(); -	ret = snd_soc_register_dai(&au1xpsc_ac97_dai); +	ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai);  	if (ret)  		goto out1; @@ -406,7 +398,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)  		return 0;  	} -	snd_soc_unregister_dai(&au1xpsc_ac97_dai); +	snd_soc_unregister_dai(&pdev->dev);  out1:  	release_mem_region(r->start, resource_size(r));  out0: @@ -422,7 +414,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)  	if (wd->dmapd)  		au1xpsc_pcm_destroy(wd->dmapd); -	snd_soc_unregister_dai(&au1xpsc_ac97_dai); +	snd_soc_unregister_dai(&pdev->dev);  	/* disable PSC completely */  	au_writel(0, AC97_CFG(wd)); @@ -485,7 +477,7 @@ static struct dev_pm_ops au1xpscac97_pmops = {  static struct platform_driver au1xpsc_ac97_driver = {  	.driver	= { -		.name	= "au1xpsc_ac97", +		.name	= "au1xpsc-ac97",  		.owner	= THIS_MODULE,  		.pm	= AU1XPSCAC97_PMOPS,  	}, diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 6083fe7799fa..94e560a8756d 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -263,27 +263,19 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  	return ret;  } -static int au1xpsc_i2s_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int au1xpsc_i2s_probe(struct snd_soc_dai *dai)  {  	return 	au1xpsc_i2s_workdata ? 0 : -ENODEV;  } -static void au1xpsc_i2s_remove(struct platform_device *pdev, -			       struct snd_soc_dai *dai) -{ -} -  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", +static struct snd_soc_dai_driver au1xpsc_i2s_dai = {  	.probe			= au1xpsc_i2s_probe, -	.remove			= au1xpsc_i2s_remove,  	.playback = {  		.rates		= AU1XPSC_I2S_RATES,  		.formats	= AU1XPSC_I2S_FMTS, @@ -298,7 +290,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {  	},  	.ops = &au1xpsc_i2s_dai_ops,  }; -EXPORT_SYMBOL(au1xpsc_i2s_dai);  static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)  { @@ -346,7 +337,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)  	 * time out.  	 */ -	ret = snd_soc_register_dai(&au1xpsc_i2s_dai); +	ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai);  	if (ret)  		goto out1; @@ -358,7 +349,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)  		return 0;  	} -	snd_soc_unregister_dai(&au1xpsc_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev);  out1:  	release_mem_region(r->start, resource_size(r));  out0: @@ -374,7 +365,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)  	if (wd->dmapd)  		au1xpsc_pcm_destroy(wd->dmapd); -	snd_soc_unregister_dai(&au1xpsc_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev);  	au_writel(0, I2S_CFG(wd));  	au_sync(); @@ -436,7 +427,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = {  static struct platform_driver au1xpsc_i2s_driver = {  	.driver		= { -		.name	= "au1xpsc_i2s", +		.name	= "au1xpsc",  		.owner	= THIS_MODULE,  		.pm	= AU1XPSCI2S_PMOPS,  	}, diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index 093775d4dc3e..f281443fd52f 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h @@ -16,9 +16,6 @@  #ifndef _AU1X_PCM_H  #define _AU1X_PCM_H -extern struct snd_soc_dai au1xpsc_ac97_dai; -extern struct snd_soc_dai au1xpsc_i2s_dai; -extern struct snd_soc_platform au1xpsc_soc_platform;  extern struct snd_ac97_bus_ops soc_ac97_ops;  /* DBDMA helpers */ diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 5e7aacf3bb5a..5a2fd8abaefa 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,  	return ret;  } -struct snd_soc_platform bf5xx_ac97_soc_platform = { -	.name		= "bf5xx-audio", -	.pcm_ops 	= &bf5xx_pcm_ac97_ops, +static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = { +	.ops			= &bf5xx_pcm_ac97_ops,  	.pcm_new	= bf5xx_pcm_ac97_new,  	.pcm_free	= bf5xx_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); -static int __init bfin_ac97_init(void) +static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&bf5xx_ac97_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);  } -module_init(bfin_ac97_init); -static void __exit bfin_ac97_exit(void) +static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver bf5xx_pcm_driver = { +	.driver = { +			.name = "bf5xx-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = bf5xx_soc_platform_probe, +	.remove = __devexit_p(bf5xx_soc_platform_remove), +}; + +static int __init snd_bf5xx_pcm_init(void) +{ +	return platform_driver_register(&bf5xx_pcm_driver); +} +module_init(snd_bf5xx_pcm_init); + +static void __exit snd_bf5xx_pcm_exit(void) +{ +	platform_driver_unregister(&bf5xx_pcm_driver);  } -module_exit(bfin_ac97_exit); +module_exit(snd_bf5xx_pcm_exit);  MODULE_AUTHOR("Cliff Cai");  MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h index 350125a0ae21..d324d5826a9b 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.h +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.h @@ -23,7 +23,4 @@ struct bf5xx_gpio {  	u32 frm;  }; -/* platform data */ -extern struct snd_soc_platform bf5xx_ac97_soc_platform; -  #endif diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index c0eba5109980..c5f856ec27ca 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);  #ifdef CONFIG_PM  static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)  { -	struct sport_device *sport = dai->private_data; +	struct sport_device *sport = snd_soc_dai_get_drvdata(dai);  	pr_debug("%s : sport %d\n", __func__, dai->id);  	if (!dai->active) @@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)  static int bf5xx_ac97_resume(struct snd_soc_dai *dai)  {  	int ret; -	struct sport_device *sport = dai->private_data; +	struct sport_device *sport = snd_soc_dai_get_drvdata(dai);  	pr_debug("%s : sport %d\n", __func__, dai->id);  	if (!dai->active) @@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)  #define bf5xx_ac97_resume	NULL  #endif -static int bf5xx_ac97_probe(struct platform_device *pdev, -			    struct snd_soc_dai *dai) +static int bf5xx_ac97_probe(struct snd_soc_dai *dai)  {  	int ret = 0;  	cmd_count = (int *)get_zeroed_page(GFP_KERNEL); @@ -379,8 +378,7 @@ peripheral_err:  	return ret;  } -static void bf5xx_ac97_remove(struct platform_device *pdev, -			      struct snd_soc_dai *dai) +static int bf5xx_ac97_remove(struct snd_soc_dai *dai)  {  	free_page((unsigned long)cmd_count);  	cmd_count = NULL; @@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,  #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET  	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);  #endif +	return 0;  } -struct snd_soc_dai bfin_ac97_dai = { -	.name = "bf5xx-ac97", -	.id = 0, +struct snd_soc_dai_driver bfin_ac97_dai = {  	.ac97_control = 1,  	.probe = bf5xx_ac97_probe,  	.remove = bf5xx_ac97_remove, @@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = {  };  EXPORT_SYMBOL_GPL(bfin_ac97_dai); +static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); +} + +static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver asoc_bfin_ac97_driver = { +	.driver = { +			.name = "bfin-ac97", +			.owner = THIS_MODULE, +	}, + +	.probe = asoc_bfin_ac97_probe, +	.remove = __devexit_p(asoc_bfin_ac97_remove), +}; +  static int __init bfin_ac97_init(void)  { -	return snd_soc_register_dai(&bfin_ac97_dai); +	return platform_driver_register(&asoc_bfin_ac97_driver);  }  module_init(bfin_ac97_init);  static void __exit bfin_ac97_exit(void)  { -	snd_soc_unregister_dai(&bfin_ac97_dai); +	platform_driver_unregister(&asoc_bfin_ac97_driver);  }  module_exit(bfin_ac97_exit); +  MODULE_AUTHOR("Roy Huang");  MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");  MODULE_LICENSE("GPL"); diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index a1f97dd809d6..15c635e33f4d 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h @@ -50,8 +50,6 @@ struct ac97_frame {  #define TAG_PCM_SR		0x0080  #define TAG_PCM_LFE		0x0040 -extern struct snd_soc_dai bfin_ac97_dai; -  void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \  		size_t count, unsigned int chan_mask); diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index 0f45a3f56be8..2394bff2b655 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836;  static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -	cpu_dai->private_data = sport_handle; +	snd_soc_dai_set_drvdata(cpu_dai, sport_handle);  	return 0;  } @@ -50,8 +50,8 @@ static int bf5xx_ad1836_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 *cpu_dai = rtd->dai->cpu_dai; -	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};  	int ret = 0;  	/* set cpu DAI configuration */ @@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {  static struct snd_soc_dai_link bf5xx_ad1836_dai = {  	.name = "ad1836",  	.stream_name = "AD1836", -	.cpu_dai = &bf5xx_tdm_dai, -	.codec_dai = &ad1836_dai, +	.cpu_dai_name = "bf5xx-tdm", +	.codec_dai_name = "ad1836-hifi", +	.platform_name = "bf5xx-tdm-pcm-audio", +	.codec_name = "ad1836-codec.0",  	.ops = &bf5xx_ad1836_ops,  };  static struct snd_soc_card bf5xx_ad1836 = {  	.name = "bf5xx_ad1836", -	.platform = &bf5xx_tdm_soc_platform,  	.dai_link = &bf5xx_ad1836_dai,  	.num_links = 1,  }; -static struct snd_soc_device bf5xx_ad1836_snd_devdata = { -	.card = &bf5xx_ad1836, -	.codec_dev = &soc_codec_dev_ad1836, -}; -  static struct platform_device *bfxx_ad1836_snd_device;  static int __init bf5xx_ad1836_init(void) @@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void)  	if (!bfxx_ad1836_snd_device)  		return -ENOMEM; -	platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); -	bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev; +	platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836);  	ret = platform_device_add(bfxx_ad1836_snd_device);  	if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index b8c9060cfd8e..e4a625317a1a 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c @@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x;  static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -	cpu_dai->private_data = sport_handle; +	snd_soc_dai_set_drvdata(cpu_dai, sport_handle);  	return 0;  } @@ -59,8 +59,8 @@ static int bf5xx_ad193x_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 *cpu_dai = rtd->dai->cpu_dai; -	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};  	int ret = 0;  	/* set cpu DAI configuration */ @@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = {  static struct snd_soc_dai_link bf5xx_ad193x_dai = {  	.name = "ad193x",  	.stream_name = "AD193X", -	.cpu_dai = &bf5xx_tdm_dai, -	.codec_dai = &ad193x_dai, +	.cpu_dai_name = "bf5xx-tdm", +	.codec_dai_name ="ad193x-hifi", +	.platform_name = "bf5xx-tdm-pcm-audio", +	.codec_name = "ad193x-codec.5",  	.ops = &bf5xx_ad193x_ops,  };  static struct snd_soc_card bf5xx_ad193x = {  	.name = "bf5xx_ad193x", -	.platform = &bf5xx_tdm_soc_platform,  	.dai_link = &bf5xx_ad193x_dai,  	.num_links = 1,  }; -static struct snd_soc_device bf5xx_ad193x_snd_devdata = { -	.card = &bf5xx_ad193x, -	.codec_dev = &soc_codec_dev_ad193x, -}; -  static struct platform_device *bfxx_ad193x_snd_device;  static int __init bf5xx_ad193x_init(void) @@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void)  	if (!bfxx_ad193x_snd_device)  		return -ENOMEM; -	platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata); -	bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev; +	platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x);  	ret = platform_device_add(bfxx_ad193x_snd_device);  	if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index d8f591273778..a31bdf656fce 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c @@ -48,10 +48,10 @@ static struct snd_soc_card bf5xx_board;  static int bf5xx_board_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	pr_debug("%s enter\n", __func__); -	cpu_dai->private_data = sport_handle; +	snd_soc_dai_set_drvdata(cpu_dai, sport_handle);  	return 0;  } @@ -62,23 +62,19 @@ static struct snd_soc_ops bf5xx_board_ops = {  static struct snd_soc_dai_link bf5xx_board_dai = {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &bfin_ac97_dai, -	.codec_dai = &ad1980_dai, +	.cpu_dai_name = "bfin-ac97", +	.codec_dai_name = "ad1980-hifi", +	.platform_name = "bfin-pcm-audio", +	.codec_name = "ad1980-codec",  	.ops = &bf5xx_board_ops,  };  static struct snd_soc_card bf5xx_board = {  	.name = "bf5xx-board", -	.platform = &bf5xx_ac97_soc_platform,  	.dai_link = &bf5xx_board_dai,  	.num_links = 1,  }; -static struct snd_soc_device bf5xx_board_snd_devdata = { -	.card = &bf5xx_board, -	.codec_dev = &soc_codec_dev_ad1980, -}; -  static struct platform_device *bf5xx_board_snd_device;  static int __init bf5xx_board_init(void) @@ -89,8 +85,7 @@ static int __init bf5xx_board_init(void)  	if (!bf5xx_board_snd_device)  		return -ENOMEM; -	platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata); -	bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev; +	platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board);  	ret = platform_device_add(bf5xx_board_snd_device);  	if (ret) diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 9825b71d0e28..900ced54ac79 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c @@ -47,7 +47,6 @@  #include "../codecs/ad73311.h"  #include "bf5xx-sport.h"  #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h"  #if CONFIG_SND_BF5XX_SPORT_NUM == 0  #define bfin_write_SPORT_TCR1	bfin_write_SPORT0_TCR1 @@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev)  static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	pr_debug("%s enter\n", __func__); -	cpu_dai->private_data = sport_handle; +	snd_soc_dai_set_drvdata(cpu_dai, sport_handle);  	return 0;  } @@ -161,7 +160,7 @@ static int bf5xx_ad73311_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 *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret = 0;  	pr_debug("%s rate %d format %x\n", __func__, params_rate(params), @@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = {  static struct snd_soc_dai_link bf5xx_ad73311_dai = {  	.name = "ad73311",  	.stream_name = "AD73311", -	.cpu_dai = &bf5xx_i2s_dai, -	.codec_dai = &ad73311_dai, +	.cpu_dai_name = "bf5xx-i2s", +	.codec_dai_name = "ad73311-hifi", +	.platform_name = "bfin-pcm-audio", +	.codec_name = "ad73311-codec",  	.ops = &bf5xx_ad73311_ops,  };  static struct snd_soc_card bf5xx_ad73311 = {  	.name = "bf5xx_ad73311", -	.platform = &bf5xx_i2s_soc_platform,  	.probe = bf5xx_probe,  	.dai_link = &bf5xx_ad73311_dai,  	.num_links = 1,  }; -static struct snd_soc_device bf5xx_ad73311_snd_devdata = { -	.card = &bf5xx_ad73311, -	.codec_dev = &soc_codec_dev_ad73311, -}; -  static struct platform_device *bf5xx_ad73311_snd_device;  static int __init bf5xx_ad73311_init(void) @@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void)  	if (!bf5xx_ad73311_snd_device)  		return -ENOMEM; -	platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); -	bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev; +	platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311);  	ret = platform_device_add(bf5xx_ad73311_snd_device);  	if (ret) diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 1d2a1adf2575..890a0dccf902 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -40,7 +40,6 @@  #include <asm/dma.h>  #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h"  #include "bf5xx-sport.h"  static void bf5xx_dma_irq(void *data) @@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,  	return ret;  } -struct snd_soc_platform bf5xx_i2s_soc_platform = { -	.name		= "bf5xx-audio", -	.pcm_ops 	= &bf5xx_pcm_i2s_ops, +static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { +	.ops		= &bf5xx_pcm_i2s_ops,  	.pcm_new	= bf5xx_pcm_i2s_new,  	.pcm_free	= bf5xx_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); -static int __init bfin_i2s_init(void) +static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&bf5xx_i2s_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);  } -module_init(bfin_i2s_init); -static void __exit bfin_i2s_exit(void) +static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver bfin_i2s_pcm_driver = { +	.driver = { +			.name = "bfin-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = bfin_i2s_soc_platform_probe, +	.remove = __devexit_p(bfin_i2s_soc_platform_remove), +}; + +static int __init snd_bfin_i2s_pcm_init(void) +{ +	return platform_driver_register(&bfin_i2s_pcm_driver); +} +module_init(snd_bfin_i2s_pcm_init); + +static void __exit snd_bfin_i2s_pcm_exit(void) +{ +	platform_driver_unregister(&bfin_i2s_pcm_driver);  } -module_exit(bfin_i2s_exit); +module_exit(snd_bfin_i2s_pcm_exit);  MODULE_AUTHOR("Cliff Cai");  MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h index 4d4609a97c59..0c2c5a68d4ff 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.h +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h @@ -23,7 +23,4 @@ struct bf5xx_gpio {  	u32 frm;  }; -/* platform data */ -extern struct snd_soc_platform bf5xx_i2s_soc_platform; -  #endif diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 3e6ada0dd1c4..d453b1e9d607 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -42,7 +42,6 @@  #include <linux/gpio.h>  #include "bf5xx-sport.h" -#include "bf5xx-i2s.h"  struct bf5xx_i2s_port {  	u16 tcr1; @@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,  		bf5xx_i2s.configured = 0;  } -static int bf5xx_i2s_probe(struct platform_device *pdev, -			   struct snd_soc_dai *dai) +static int bf5xx_i2s_probe(struct snd_soc_dai *dai)  {  	pr_debug("%s enter\n", __func__);  	if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { @@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,  	return 0;  } -static void bf5xx_i2s_remove(struct platform_device *pdev, -			struct snd_soc_dai *dai) +static int bf5xx_i2s_remove(struct snd_soc_dai *dai)  {  	pr_debug("%s enter\n", __func__);  	peripheral_free_list(&sport_req[sport_num][0]); +	return 0;  }  #ifdef CONFIG_PM @@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)  	pr_debug("%s : sport %d\n", __func__, dai->id); -	if (dai->capture.active) +	if (dai->capture_active)  		sport_rx_stop(sport_handle); -	if (dai->playback.active) +	if (dai->playback_active)  		sport_tx_stop(sport_handle);  	return 0;  } @@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {  	.set_fmt	= bf5xx_i2s_set_dai_fmt,  }; -struct snd_soc_dai bf5xx_i2s_dai = { -	.name = "bf5xx-i2s", -	.id = 0, +static struct snd_soc_dai_driver bf5xx_i2s_dai = {  	.probe = bf5xx_i2s_probe,  	.remove = bf5xx_i2s_remove,  	.suspend = bf5xx_i2s_suspend, @@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = {  		.formats = BF5XX_I2S_FORMATS,},  	.ops = &bf5xx_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); + +static int bfin_i2s_drv_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); +} + +static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver bfin_i2s_driver = { +	.probe = bfin_i2s_drv_probe, +	.remove = __devexit_p(bfin_i2s_drv_remove), + +	.driver = { +		.name = "bf5xx-i2s", +		.owner = THIS_MODULE, +	}, +};  static int __init bfin_i2s_init(void)  { -	return snd_soc_register_dai(&bf5xx_i2s_dai); +	return platform_driver_register(&bfin_i2s_driver);  } -module_init(bfin_i2s_init);  static void __exit bfin_i2s_exit(void)  { -	snd_soc_unregister_dai(&bf5xx_i2s_dai); +	platform_driver_unregister(&bfin_i2s_driver);  } + +module_init(bfin_i2s_init);  module_exit(bfin_i2s_exit);  /* Module information */ diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h deleted file mode 100644 index 264ecdcba35a..000000000000 --- a/sound/soc/blackfin/bf5xx-i2s.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-i2s.h - * - * 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 _BF5XX_I2S_H -#define _BF5XX_I2S_H - -extern struct snd_soc_dai bf5xx_i2s_dai; - -#endif diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index 3a00fa4dbe6d..36f2769eb912 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c @@ -42,17 +42,16 @@  #include "../codecs/ssm2602.h"  #include "bf5xx-sport.h"  #include "bf5xx-i2s-pcm.h" -#include "bf5xx-i2s.h"  static struct snd_soc_card bf5xx_ssm2602;  static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	pr_debug("%s enter\n", __func__); -	cpu_dai->private_data = sport_handle; +	snd_soc_dai_set_drvdata(cpu_dai, sport_handle);  	return 0;  } @@ -60,8 +59,8 @@ static int bf5xx_ssm2602_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0; @@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {  static struct snd_soc_dai_link bf5xx_ssm2602_dai = {  	.name = "ssm2602",  	.stream_name = "SSM2602", -	.cpu_dai = &bf5xx_i2s_dai, -	.codec_dai = &ssm2602_dai, +	.cpu_dai_name = "bf5xx-i2s", +	.codec_dai_name = "ssm2602-hifi", +	.platform_name = "bf5xx-pcm-audio", +	.codec_name = "ssm2602-codec.0-0x1b",  	.ops = &bf5xx_ssm2602_ops,  }; -/* - * SSM2602 2 wire address is determined by CSB - * state during powerup. - *    low  = 0x1a - *    high = 0x1b - */ - -static struct ssm2602_setup_data bf5xx_ssm2602_setup = { -	.i2c_bus = 0, -	.i2c_address = 0x1b, -}; -  static struct snd_soc_card bf5xx_ssm2602 = {  	.name = "bf5xx_ssm2602", -	.platform = &bf5xx_i2s_soc_platform,  	.dai_link = &bf5xx_ssm2602_dai,  	.num_links = 1,  }; -static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { -	.card = &bf5xx_ssm2602, -	.codec_dev = &soc_codec_dev_ssm2602, -	.codec_data = &bf5xx_ssm2602_setup, -}; -  static struct platform_device *bf5xx_ssm2602_snd_device;  static int __init bf5xx_ssm2602_init(void) @@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void)  	if (!bf5xx_ssm2602_snd_device)  		return -ENOMEM; -	platform_set_drvdata(bf5xx_ssm2602_snd_device, -				&bf5xx_ssm2602_snd_devdata); -	bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; +	platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602);  	ret = platform_device_add(bf5xx_ssm2602_snd_device);  	if (ret) diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 6bac1ac1a315..74cf759b78a6 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c @@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = bf5xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -307,25 +307,44 @@ out:  	return ret;  } -struct snd_soc_platform bf5xx_tdm_soc_platform = { -	.name           = "bf5xx-audio", -	.pcm_ops        = &bf5xx_pcm_tdm_ops, +static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = { +	.ops        = &bf5xx_pcm_tdm_ops,  	.pcm_new        = bf5xx_pcm_tdm_new,  	.pcm_free       = bf5xx_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform); -static int __init bfin_pcm_tdm_init(void) +static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&bf5xx_tdm_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);  } -module_init(bfin_pcm_tdm_init); -static void __exit bfin_pcm_tdm_exit(void) +static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver bfin_tdm_driver = { +	.driver = { +			.name = "bf5xx-tdm-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = bf5xx_soc_platform_probe, +	.remove = __devexit_p(bf5xx_soc_platform_remove), +}; + +static int __init snd_bfin_tdm_init(void) +{ +	return platform_driver_register(&bfin_tdm_driver); +} +module_init(snd_bfin_tdm_init); + +static void __exit snd_bfin_tdm_exit(void) +{ +	platform_driver_unregister(&bfin_tdm_driver);  } -module_exit(bfin_pcm_tdm_exit); +module_exit(snd_bfin_tdm_exit);  MODULE_AUTHOR("Barry Song");  MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h index ddc5047df88c..7f8cc01c4477 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h @@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params {  	char *name;                     /* stream identifier */  }; -/* platform data */ -extern struct snd_soc_platform bf5xx_tdm_soc_platform; -  #endif diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 24c14269f4bc..125123929f16 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c @@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)  	if (!dai->active)  		return 0; -	if (dai->capture.active) +	if (dai->capture_active)  		sport_rx_stop(sport); -	if (dai->playback.active) +	if (dai->playback_active)  		sport_tx_stop(sport);  	return 0;  } @@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)  static int bf5xx_tdm_resume(struct snd_soc_dai *dai)  {  	int ret; -	struct sport_device *sport = dai->private_data; +	struct sport_device *sport = snd_soc_dai_get_drvdata(dai);  	if (!dai->active)  		return 0; @@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {  	.set_channel_map   = bf5xx_tdm_set_channel_map,  }; -struct snd_soc_dai bf5xx_tdm_dai = { -	.name = "bf5xx-tdm", -	.id = 0, +static struct snd_soc_dai_driver bf5xx_tdm_dai = {  	.suspend = bf5xx_tdm_suspend,  	.resume = bf5xx_tdm_resume,  	.playback = { @@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = {  		.formats = SNDRV_PCM_FMTBIT_S32_LE,},  	.ops = &bf5xx_tdm_dai_ops,  }; -EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);  static int __devinit bfin_tdm_probe(struct platform_device *pdev)  { @@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)  		goto sport_config_err;  	} -	ret = snd_soc_register_dai(&bf5xx_tdm_dai); +	ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);  	if (ret) {  		pr_err("Failed to register DAI: %d\n", ret);  		goto sport_config_err; @@ -337,7 +334,7 @@ sport_config_err:  static int __devexit bfin_tdm_remove(struct platform_device *pdev)  {  	peripheral_free_list(&sport_req[sport_num][0]); -	snd_soc_unregister_dai(&bf5xx_tdm_dai); +	snd_soc_unregister_dai(&pdev->dev);  	return 0;  } diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h index 04189a18c1ba..e986a3ea3315 100644 --- a/sound/soc/blackfin/bf5xx-tdm.h +++ b/sound/soc/blackfin/bf5xx-tdm.h @@ -20,6 +20,4 @@ struct bf5xx_tdm_port {  	int configured;  }; -extern struct snd_soc_dai bf5xx_tdm_dai; -  #endif diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 1f5e57a4bb7a..12c87d37eba1 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -21,7 +21,6 @@  #include <sound/ac97_codec.h>  #include <sound/initval.h>  #include <sound/soc.h> -#include "ac97.h"  #define AC97_VERSION "0.6" @@ -30,8 +29,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?  		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; @@ -46,8 +44,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = {  	.prepare	= ac97_prepare,  }; -struct snd_soc_dai ac97_dai = { -	.name = "AC97 HiFi", +static struct snd_soc_dai_driver ac97_dai = { +	.name = "ac97-hifi",  	.ac97_control = 1,  	.playback = {  		.stream_name = "AC97 Playback", @@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = {  		.formats = SND_SOC_STD_AC97_FMTS,},  	.ops = &ac97_dai_ops,  }; -EXPORT_SYMBOL_GPL(ac97_dai);  static unsigned int ac97_read(struct snd_soc_codec *codec,  	unsigned int reg) @@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,  	return 0;  } -static int ac97_soc_probe(struct platform_device *pdev) +static int ac97_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_codec *codec;  	struct snd_ac97_bus *ac97_bus;  	struct snd_ac97_template ac97_template; -	int i; -	int ret = 0; +	int ret;  	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (!socdev->card->codec) -		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->name = "AC97"; -	codec->owner = THIS_MODULE; -	codec->dai = &ac97_dai; -	codec->num_dai = 1; -	codec->write = ac97_write; -	codec->read = ac97_read; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto err; +	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); +	if (ret < 0) { +		printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); +		return ret; +	}  	/* add codec as bus device for standard ac97 */ -	ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus); +	ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);  	if (ret < 0) -		goto bus_err; +		return ret;  	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));  	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);  	if (ret < 0) -		goto bus_err; - -	for (i = 0; i < card->num_links; i++) { -		if (card->dai_link[i].codec_dai->ac97_control) { -			snd_ac97_dev_add_pdata(codec->ac97, -				card->dai_link[i].cpu_dai->ac97_pdata); -		} -	} +		return ret;  	return 0; - -bus_err: -	snd_soc_free_pcms(socdev); - -err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL; -	return ret;  } -static int ac97_soc_remove(struct platform_device *pdev) +static int ac97_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (!codec) -		return 0; - -	snd_soc_free_pcms(socdev); -	kfree(socdev->card->codec); -  	return 0;  }  #ifdef CONFIG_PM -static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_ac97_suspend(socdev->card->codec->ac97); +	snd_ac97_suspend(codec->ac97);  	return 0;  } -static int ac97_soc_resume(struct platform_device *pdev) +static int ac97_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_ac97_resume(socdev->card->codec->ac97); +	snd_ac97_resume(codec->ac97);  	return 0;  } @@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev)  #define ac97_soc_resume NULL  #endif -struct snd_soc_codec_device soc_codec_dev_ac97 = { +static struct snd_soc_codec_driver soc_codec_dev_ac97 = { +	.write = ac97_write, +	.read = ac97_read,  	.probe = 	ac97_soc_probe,  	.remove = 	ac97_soc_remove,  	.suspend =	ac97_soc_suspend,  	.resume =	ac97_soc_resume,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); + +static __devinit int ac97_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_ac97, &ac97_dai, 1); +} + +static int __devexit ac97_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver ac97_codec_driver = { +	.driver = { +			.name = "ac97-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = ac97_probe, +	.remove = __devexit_p(ac97_remove), +}; + +static int __init ac97_init(void) +{ +	return platform_driver_register(&ac97_codec_driver); +} +module_init(ac97_init); + +static void __exit ac97_exit(void) +{ +	platform_driver_unregister(&ac97_codec_driver); +} +module_exit(ac97_exit);  MODULE_DESCRIPTION("Soc Generic AC97 driver");  MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h deleted file mode 100644 index 281aa42e2bbb..000000000000 --- a/sound/soc/codecs/ac97.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/sound/codecs/ac97.h -- ALSA SoC Layer - * - * Author:		Liam Girdwood - * Created:		Dec 1st 2005 - * Copyright:	Wolfson Microelectronics. PLC. - * - * 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 __LINUX_SND_SOC_AC97_H -#define __LINUX_SND_SOC_AC97_H - -extern struct snd_soc_codec_device soc_codec_dev_ac97; -extern struct snd_soc_dai ac97_dai; - -#endif diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a01006c8c606..d272534c8f84 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -33,15 +33,10 @@  /* codec private data */  struct ad1836_priv { -	struct snd_soc_codec codec; -	u16 reg_cache[AD1836_NUM_REGS]; +	enum snd_soc_control_type control_type; +	void *control_data;  }; -static struct snd_soc_codec *ad1836_codec; -struct snd_soc_codec_device soc_codec_dev_ad1836; -static int ad1836_register(struct ad1836_priv *ad1836); -static void ad1836_unregister(struct ad1836_priv *ad1836); -  /*   * AD1836 volume/mute/de-emphasis etc. controls   */ @@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,  	int word_len = 0;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	/* bit size */  	switch (params_format(params)) { @@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,  }  #ifdef CONFIG_PM -static int ad1836_soc_suspend(struct platform_device *pdev, +static int ad1836_soc_suspend(struct snd_soc_codec *codec,  		pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	/* reset clock control mode */  	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);  	adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; @@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,  	return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);  } -static int ad1836_soc_resume(struct platform_device *pdev) +static int ad1836_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	/* restore clock control mode */  	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);  	adc_ctrl2 |= AD1836_ADC_AUX; @@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)  #define ad1836_soc_resume  NULL  #endif -static int __devinit ad1836_spi_probe(struct spi_device *spi) -{ -	struct snd_soc_codec *codec; -	struct ad1836_priv *ad1836; - -	ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); -	if (ad1836 == NULL) -		return -ENOMEM; - -	codec = &ad1836->codec; -	codec->control_data = spi; -	codec->dev = &spi->dev; - -	dev_set_drvdata(&spi->dev, ad1836); - -	return ad1836_register(ad1836); -} - -static int __devexit ad1836_spi_remove(struct spi_device *spi) -{ -	struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev); - -	ad1836_unregister(ad1836); -	return 0; -} - -static struct spi_driver ad1836_spi_driver = { -	.driver = { -		.name	= "ad1836", -		.owner	= THIS_MODULE, -	}, -	.probe		= ad1836_spi_probe, -	.remove		= __devexit_p(ad1836_spi_remove), -}; -  static struct snd_soc_dai_ops ad1836_dai_ops = {  	.hw_params = ad1836_hw_params,  	.set_fmt = ad1836_set_dai_fmt,  };  /* codec DAI instance */ -struct snd_soc_dai ad1836_dai = { -	.name = "AD1836", +static struct snd_soc_dai_driver ad1836_dai = { +	.name = "ad1836-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {  	},  	.ops = &ad1836_dai_ops,  }; -EXPORT_SYMBOL_GPL(ad1836_dai); -static int ad1836_register(struct ad1836_priv *ad1836) +static int ad1836_probe(struct snd_soc_codec *codec)  { -	int ret; -	struct snd_soc_codec *codec = &ad1836->codec; - -	if (ad1836_codec) { -		dev_err(codec->dev, "Another ad1836 is registered\n"); -		kfree(ad1836); -		return -EINVAL; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	snd_soc_codec_set_drvdata(codec, ad1836); -	codec->reg_cache = ad1836->reg_cache; -	codec->reg_cache_size = AD1836_NUM_REGS; -	codec->name = "AD1836"; -	codec->owner = THIS_MODULE; -	codec->dai = &ad1836_dai; -	codec->num_dai = 1; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	ad1836_dai.dev = codec->dev; -	ad1836_codec = codec; +	struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); +	int ret = 0; +	codec->control_data = ad1836->control_data;  	ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);  	if (ret < 0) {  		dev_err(codec->dev, "failed to set cache I/O: %d\n", @@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)  	snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);  	snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		kfree(ad1836); -		return ret; -	} - -	ret = snd_soc_register_dai(&ad1836_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		kfree(ad1836); -		return ret; -	} - -	return 0; -} - -static void ad1836_unregister(struct ad1836_priv *ad1836) -{ -	snd_soc_unregister_dai(&ad1836_dai); -	snd_soc_unregister_codec(&ad1836->codec); -	kfree(ad1836); -	ad1836_codec = NULL; -} - -static int ad1836_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (ad1836_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = ad1836_codec; -	codec = ad1836_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: %d\n", ret); -		goto pcm_err; -	} -  	snd_soc_add_controls(codec, ad1836_snd_controls,  			     ARRAY_SIZE(ad1836_snd_controls));  	snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,  				  ARRAY_SIZE(ad1836_dapm_widgets));  	snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); -pcm_err:  	return ret;  }  /* power down chip */ -static int ad1836_remove(struct platform_device *pdev) +static int ad1836_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	/* reset clock control mode */ +	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); +	adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; -	return 0; +	return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);  } -struct snd_soc_codec_device soc_codec_dev_ad1836 = { +static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {  	.probe = 	ad1836_probe,  	.remove = 	ad1836_remove,  	.suspend =      ad1836_soc_suspend,  	.resume =       ad1836_soc_resume, +	.reg_cache_size = AD1836_NUM_REGS, +	.reg_word_size = sizeof(u16), +}; + +static int __devinit ad1836_spi_probe(struct spi_device *spi) +{ +	struct ad1836_priv *ad1836; +	int ret; + +	ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); +	if (ad1836 == NULL) +		return -ENOMEM; + +	spi_set_drvdata(spi, ad1836); +	ad1836->control_data = spi; +	ad1836->control_type = SND_SOC_SPI; + +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_ad1836, &ad1836_dai, 1); +	if (ret < 0) +		kfree(ad1836); +	return ret; +} + +static int __devexit ad1836_spi_remove(struct spi_device *spi) +{ +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi)); +	return 0; +} + +static struct spi_driver ad1836_spi_driver = { +	.driver = { +		.name	= "ad1836-codec", +		.owner	= THIS_MODULE, +	}, +	.probe		= ad1836_spi_probe, +	.remove		= __devexit_p(ad1836_spi_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);  static int __init ad1836_init(void)  { diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index e9d90d3951c5..845596717fdf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -60,6 +60,4 @@  #define AD1836_NUM_REGS                16 -extern struct snd_soc_dai ad1836_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1836;  #endif diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 1def75e4862f..fa2834c91b9f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -24,9 +24,10 @@  /* codec private data */  struct ad193x_priv { -	unsigned int sysclk; -	struct snd_soc_codec codec;  	u8 reg_cache[AD193X_NUM_REGS]; +	enum snd_soc_control_type bus_type; +	void *control_data; +	int sysclk;  };  /* ad193x register cache & default register settings */ @@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = {  	0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,  }; -static struct snd_soc_codec *ad193x_codec; -struct snd_soc_codec_device soc_codec_dev_ad193x; -  /*   * AD193X volume/mute/de-emphasis etc. controls   */ @@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,  	int word_len = 0, reg = 0, master_rate = 0;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);  	/* bit size */ @@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,  	return 0;  } -static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) -{ -	struct snd_soc_codec *codec; -	struct ad193x_priv *ad193x; -	int ret; - -	if (ad193x_codec) { -		dev_err(dev, "Another ad193x is registered\n"); -		return -EINVAL; -	} - -	ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); -	if (ad193x == NULL) -		return -ENOMEM; - -	dev_set_drvdata(dev, ad193x); - -	codec = &ad193x->codec; -	mutex_init(&codec->mutex); -	codec->control_data = ctrl_data; -	codec->dev = dev; -	snd_soc_codec_set_drvdata(codec, ad193x); -	codec->reg_cache = ad193x->reg_cache; -	codec->reg_cache_size = AD193X_NUM_REGS; -	codec->name = "AD193X"; -	codec->owner = THIS_MODULE; -	codec->dai = &ad193x_dai; -	codec->num_dai = 1; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	ad193x_dai.dev = codec->dev; -	ad193x_codec = codec; - -	memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS); - -	if (bus_type == SND_SOC_I2C) -		ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type); -	else -		ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); -	if (ret < 0) { -		dev_err(codec->dev, "failed to set cache I/O: %d\n", -				ret); -		kfree(ad193x); -		return ret; -	} - -	/* default setting for ad193x */ - -	/* unmute dac channels */ -	snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); -	/* de-emphasis: 48kHz, powedown dac */ -	snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); -	/* powerdown dac, dac in tdm mode */ -	snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); -	/* high-pass filter enable */ -	snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); -	/* sata delay=1, adc aux mode */ -	snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); -	/* pll input: mclki/xi */ -	snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ -	snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); -	ad193x->sysclk = 12288000; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		kfree(ad193x); -		return ret; -	} - -	ret = snd_soc_register_dai(&ad193x_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		kfree(ad193x); -		return ret; -	} - -	return 0; -} - -static int ad193x_bus_remove(struct device *dev) -{ -	struct ad193x_priv *ad193x = dev_get_drvdata(dev); - -	snd_soc_unregister_dai(&ad193x_dai); -	snd_soc_unregister_codec(&ad193x->codec); -	kfree(ad193x); -	ad193x_codec = NULL; - -	return 0; -} -  static struct snd_soc_dai_ops ad193x_dai_ops = {  	.hw_params = ad193x_hw_params,  	.digital_mute = ad193x_mute, @@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {  };  /* codec DAI instance */ -struct snd_soc_dai ad193x_dai = { -	.name = "AD193X", +static struct snd_soc_dai_driver ad193x_dai = { +	.name = "ad193x-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = {  	},  	.ops = &ad193x_dai_ops,  }; -EXPORT_SYMBOL_GPL(ad193x_dai); -static int ad193x_probe(struct platform_device *pdev) +static int ad193x_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; +	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); +	int ret; -	if (ad193x_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	codec->control_data = ad193x->control_data; +	if (ad193x->bus_type == SND_SOC_I2C) +		ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type); +	else +		ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type); +	if (ret < 0) { +		dev_err(codec->dev, "failed to set cache I/O: %d\n", +				ret); +		kfree(ad193x); +		return ret;  	} -	socdev->card->codec = ad193x_codec; -	codec = ad193x_codec; +	/* default setting for ad193x */ -	/* 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: %d\n", ret); -		goto pcm_err; -	} +	/* unmute dac channels */ +	snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); +	/* de-emphasis: 48kHz, powedown dac */ +	snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); +	/* powerdown dac, dac in tdm mode */ +	snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); +	/* high-pass filter enable */ +	snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); +	/* sata delay=1, adc aux mode */ +	snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); +	/* pll input: mclki/xi */ +	snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ +	snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);  	snd_soc_add_controls(codec, ad193x_snd_controls,  			     ARRAY_SIZE(ad193x_snd_controls)); @@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev)  				  ARRAY_SIZE(ad193x_dapm_widgets));  	snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); -pcm_err:  	return ret;  } -/* power down chip */ -static int ad193x_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_ad193x = { +static struct snd_soc_codec_driver soc_codec_dev_ad193x = {  	.probe = 	ad193x_probe, -	.remove = 	ad193x_remove, +	.reg_cache_default = ad193x_reg, +	.reg_cache_size = AD193X_NUM_REGS, +	.reg_word_size = sizeof(u16),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);  #if defined(CONFIG_SPI_MASTER)  static int __devinit ad193x_spi_probe(struct spi_device *spi)  { -	return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); +	struct ad193x_priv *ad193x; +	int ret; + +	ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); +	if (ad193x == NULL) +		return -ENOMEM; + +	spi_set_drvdata(spi, ad193x); +	ad193x->control_data = spi; +	ad193x->bus_type = SND_SOC_SPI; + +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_ad193x, &ad193x_dai, 1); +	if (ret < 0) +		kfree(ad193x); +	return ret;  }  static int __devexit ad193x_spi_remove(struct spi_device *spi)  { -	return ad193x_bus_remove(&spi->dev); +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi)); +	return 0;  }  static struct spi_driver ad193x_spi_driver = {  	.driver = { -		.name	= "ad193x", +		.name	= "ad193x-codec",  		.owner	= THIS_MODULE,  	},  	.probe		= ad193x_spi_probe, @@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);  static int __devinit ad193x_i2c_probe(struct i2c_client *client,  		const struct i2c_device_id *id)  { -	return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); +	struct ad193x_priv *ad193x; +	int ret; + +	ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); +	if (ad193x == NULL) +		return -ENOMEM; + +	i2c_set_clientdata(client, ad193x); +	ad193x->control_data = client; +	ad193x->bus_type = SND_SOC_I2C; + +	ret =  snd_soc_register_codec(&client->dev, +			&soc_codec_dev_ad193x, &ad193x_dai, 1); +	if (ret < 0) +		kfree(ad193x); +	return ret;  }  static int __devexit ad193x_i2c_remove(struct i2c_client *client)  { -	return ad193x_bus_remove(&client->dev); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client)); +	return 0;  }  static struct i2c_driver ad193x_i2c_driver = {  	.driver = { -		.name = "ad193x", +		.name = "ad193x-codec",  	},  	.probe    = ad193x_i2c_probe,  	.remove   = __devexit_p(ad193x_i2c_remove), diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 654ba64ae04c..9747b5497877 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -80,7 +80,4 @@  #define AD193X_NUM_REGS          17 -extern struct snd_soc_dai ad193x_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad193x; -  #endif diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 042072738cdc..1371afac657b 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,  	return 0;  } -struct snd_soc_dai ad1980_dai = { -	.name = "AC97", +struct snd_soc_dai_driver ad1980_dai = { +	.name = "ad1980-hifi",  	.ac97_control = 1,  	.playback = {  		.stream_name = "Playback", @@ -177,53 +177,20 @@ err:  	return -EIO;  } -static int ad1980_soc_probe(struct platform_device *pdev) +static int ad1980_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; +	int ret;  	u16 vendor_id2;  	u16 ext_status;  	printk(KERN_INFO "AD1980 SoC Audio Codec\n"); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (socdev->card->codec == NULL) -		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->reg_cache = -		kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} -	memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \ -			ARRAY_SIZE(ad1980_reg)); -	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg); -	codec->reg_cache_step = 2; -	codec->name = "AD1980"; -	codec->owner = THIS_MODULE; -	codec->dai = &ad1980_dai; -	codec->num_dai = 1; -	codec->write = ac97_write; -	codec->read = ac97_read; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) {  		printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); -		goto codec_err; +		return ret;  	} -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; - -  	ret = ad1980_reset(codec, 0);  	if (ret < 0) {  		printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); @@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev)  	return 0;  reset_err: -	snd_soc_free_pcms(socdev); - -pcm_err:  	snd_soc_free_ac97_codec(codec); - -codec_err: -	kfree(codec->reg_cache); - -cache_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL;  	return ret;  } -static int ad1980_soc_remove(struct platform_device *pdev) +static int ad1980_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; - -	snd_soc_dapm_free(socdev); -	snd_soc_free_pcms(socdev);  	snd_soc_free_ac97_codec(codec); -	kfree(codec->reg_cache); -	kfree(codec);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_ad1980 = { +static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {  	.probe = 	ad1980_soc_probe,  	.remove = 	ad1980_soc_remove, +	.reg_cache_size = ARRAY_SIZE(ad1980_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_step = 2, +	.write = ac97_write, +	.read = ac97_read,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); + +static __devinit int ad1980_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_ad1980, &ad1980_dai, 1); +} + +static int __devexit ad1980_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver ad1980_codec_driver = { +	.driver = { +			.name = "ad1980-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = ad1980_probe, +	.remove = __devexit_p(ad1980_remove), +}; + +static int __init ad1980_init(void) +{ +	return platform_driver_register(&ad1980_codec_driver); +} +module_init(ad1980_init); + +static void __exit ad1980_exit(void) +{ +	platform_driver_unregister(&ad1980_codec_driver); +} +module_exit(ad1980_exit);  MODULE_DESCRIPTION("ASoC ad1980 driver");  MODULE_AUTHOR("Roy Huang, Cliff Cai"); diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h index db6c8500d66b..29b5a8750926 100644 --- a/sound/soc/codecs/ad1980.h +++ b/sound/soc/codecs/ad1980.h @@ -17,7 +17,4 @@  #define PR5		0x2000  #define PR6		0x4000 -extern struct snd_soc_dai ad1980_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1980; -  #endif diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 475807bea2c2..c53955fe17b6 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -23,8 +23,8 @@  #include "ad73311.h" -struct snd_soc_dai ad73311_dai = { -	.name = "AD73311", +static struct snd_soc_dai_driver ad73311_dai = { +	.name = "ad73311-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {  		.rates = SNDRV_PCM_RATE_8000,  		.formats = SNDRV_PCM_FMTBIT_S16_LE, },  }; -EXPORT_SYMBOL_GPL(ad73311_dai); -static int ad73311_soc_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; -	mutex_init(&codec->mutex); -	codec->name = "AD73311"; -	codec->owner = THIS_MODULE; -	codec->dai = &ad73311_dai; -	codec->num_dai = 1; -	socdev->card->codec = codec; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "ad73311: failed to create pcms\n"); -		goto pcm_err; -	} - -	return ret; +static struct snd_soc_codec_driver soc_codec_dev_ad73311; -pcm_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL; -	return ret; +static int ad73311_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_ad73311, &ad73311_dai, 1);  } -static int ad73311_soc_remove(struct platform_device *pdev) +static int ad73311_remove(struct platform_device *pdev)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; -	snd_soc_free_pcms(socdev); -	kfree(codec); +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_ad73311 = { -	.probe = 	ad73311_soc_probe, -	.remove = 	ad73311_soc_remove, +static struct platform_driver ad73311_codec_driver = { +	.driver = { +			.name = "ad73311-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = ad73311_probe, +	.remove = __devexit_p(ad73311_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);  static int __init ad73311_init(void)  { -	return snd_soc_register_dai(&ad73311_dai); +	return platform_driver_register(&ad73311_codec_driver);  }  module_init(ad73311_init);  static void __exit ad73311_exit(void)  { -	snd_soc_unregister_dai(&ad73311_dai); +	platform_driver_unregister(&ad73311_codec_driver);  }  module_exit(ad73311_exit); diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h index 569573d2d4d7..4b353eefc0bf 100644 --- a/sound/soc/codecs/ad73311.h +++ b/sound/soc/codecs/ad73311.h @@ -85,6 +85,4 @@  #define REGF_INV		(1 << 6)  #define REGF_ALB		(1 << 7) -extern struct snd_soc_dai ad73311_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad73311;  #endif diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index f8e75edb27b7..8402854ec15e 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -19,16 +19,12 @@  #include <sound/initval.h>  #include <sound/soc.h> -#include "ads117x.h" -  #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) -  #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) -struct snd_soc_dai ads117x_dai = { +static struct snd_soc_dai_driver ads117x_dai = {  /* ADC */ -	.name = "ADS117X ADC", -	.id = 1, +	.name = "ads117x-hifi",  	.capture = {  		.stream_name = "Capture",  		.channels_min = 1, @@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {  		.rates = ADS117X_RATES,  		.formats = ADS117X_FORMATS,},  }; -EXPORT_SYMBOL_GPL(ads117x_dai); - -static int ads117x_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	codec->name = "ADS117X"; -	codec->owner = THIS_MODULE; -	codec->dai = &ads117x_dai; -	codec->num_dai = 1; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "ads117x: failed to create pcms\n"); -		kfree(codec); -		return ret; -	} - -	return 0; -} - -static int ads117x_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	snd_soc_free_pcms(socdev); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ads117x = { -	.probe =	ads117x_probe, -	.remove =	ads117x_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x); +static struct snd_soc_codec_driver soc_codec_dev_ads117x; -static __devinit int ads117x_platform_probe(struct platform_device *pdev) +static __devinit int ads117x_probe(struct platform_device *pdev)  { -	ads117x_dai.dev = &pdev->dev; -	return snd_soc_register_dai(&ads117x_dai); +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_ads117x, &ads117x_dai, 1);  } -static int __devexit ads117x_platform_remove(struct platform_device *pdev) +static int __devexit ads117x_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&ads117x_dai); +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  }  static struct platform_driver ads117x_codec_driver = {  	.driver = { -			.name = "ads117x", +			.name = "ads117x-codec",  			.owner = THIS_MODULE,  	}, -	.probe = ads117x_platform_probe, -	.remove = __devexit_p(ads117x_platform_remove), +	.probe = ads117x_probe, +	.remove = __devexit_p(ads117x_remove),  };  static int __init ads117x_init(void) diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h index dbcf50ec9bd1..3ce028614002 100644 --- a/sound/soc/codecs/ads117x.h +++ b/sound/soc/codecs/ads117x.h @@ -9,5 +9,5 @@   *  Free Software Foundation;  either version 2 of the  License, or (at your   *  option) any later version.   */ -extern struct snd_soc_dai ads117x_dai; -extern struct snd_soc_codec_device soc_codec_dev_ads117x; +extern struct snd_soc_dai_driver ads117x_dai; +extern struct snd_soc_codec_driver soc_codec_dev_ads117x; diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 192aebda3029..c27f8f59dc66 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -17,8 +17,6 @@  #include <linux/spi/spi.h>  #include <sound/asoundef.h> -#include "ak4104.h" -  /* AK4104 registers addresses */  #define AK4104_REG_CONTROL1		0x00  #define AK4104_REG_RESERVED		0x01 @@ -45,11 +43,11 @@  #define AK4104_TX_TXE			(1 << 0)  #define AK4104_TX_V			(1 << 1) -#define DRV_NAME "ak4104" +#define DRV_NAME "ak4104-codec"  struct ak4104_private { -	struct snd_soc_codec codec; -	u8 reg_cache[AK4104_NUM_REGS]; +	enum snd_soc_control_type control_type; +	void *control_data;  };  static int ak4104_fill_cache(struct snd_soc_codec *codec) @@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec)  	u8 *reg_cache = codec->reg_cache;  	struct spi_device *spi = codec->control_data; -	for (i = 0; i < codec->reg_cache_size; i++) { +	for (i = 0; i < codec->driver->reg_cache_size; i++) {  		int ret = spi_w8r8(spi, i | AK4104_READ);  		if (ret < 0) {  			dev_err(&spi->dev, "SPI write failure\n"); @@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,  {  	u8 *reg_cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	return reg_cache[reg]; @@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,  	u8 *cache = codec->reg_cache;  	struct spi_device *spi = codec->control_data; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	/* only write to the hardware if value has changed */ @@ -145,8 +143,7 @@ static int ak4104_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	int val = 0;  	/* set the IEC958 bits: consumer mode, no copyright bit */ @@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = {  	.set_fmt = ak4104_set_dai_fmt,  }; -struct snd_soc_dai ak4104_dai = { -	.name = DRV_NAME, +static struct snd_soc_dai_driver ak4104_dai = { +	.name = "ak4104-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = {  	.ops = &ak4101_dai_ops,  }; -static struct snd_soc_codec *ak4104_codec; - -static int ak4104_spi_probe(struct spi_device *spi) +static int ak4104_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec; -	struct ak4104_private *ak4104; +	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);  	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; -	snd_soc_codec_set_drvdata(codec, ak4104); -	codec->control_data = spi; -	codec->reg_cache = ak4104->reg_cache; -	codec->reg_cache_size = AK4104_NUM_REGS; +	codec->control_data = ak4104->control_data;  	/* 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"); +		dev_err(codec->dev, "failed to fill register cache\n");  		return ret;  	} @@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi)  	 * 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; -	} +					 AK4104_RESERVED_VAL) +		return -ENODEV;  	/* 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; +		return ret;  	/* 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; -	} +		return ret; -	spi_set_drvdata(spi, ak4104); -	dev_info(&spi->dev, "SPI device initialized\n"); +	dev_info(codec->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) +static int ak4104_remove(struct snd_soc_codec *codec)  { -	int ret, val; -	struct ak4104_private *ak4104 = spi_get_drvdata(spi); +	int val, ret; -	val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); +	val = ak4104_read_reg_cache(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; +	ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); -	ak4104_codec = NULL; -	kfree(ak4104); -	return 0; +	return ret;  } -static int ak4104_probe(struct platform_device *pdev) +static struct snd_soc_codec_driver soc_codec_device_ak4104 = { +	.probe =	ak4104_probe, +	.remove =	ak4104_remove, +	.reg_cache_size = AK4104_NUM_REGS, +	.reg_word_size = sizeof(u16), +}; + +static int ak4104_spi_probe(struct spi_device *spi)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = ak4104_codec; +	struct ak4104_private *ak4104;  	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"); +	spi->bits_per_word = 8; +	spi->mode = SPI_MODE_0; +	ret = spi_setup(spi); +	if (ret < 0)  		return ret; -	} -	return 0; +	ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); +	if (ak4104 == NULL) +		return -ENOMEM; + +	ak4104->control_data = spi; +	ak4104->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, ak4104); + +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_device_ak4104, &ak4104_dai, 1); +	if (ret < 0) +		kfree(ak4104); +	return ret;  } -static int ak4104_remove(struct platform_device *pdev) +static int __devexit ak4104_spi_remove(struct spi_device *spi)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	snd_soc_free_pcms(socdev); +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	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  = { diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h deleted file mode 100644 index eb88fe7e4def..000000000000 --- a/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/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index d4253675b2d3..cd88c8f32a38 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -31,11 +31,11 @@  #define AK4535_VERSION "0.3" -struct snd_soc_codec_device soc_codec_dev_ak4535; -  /* codec private data */  struct ak4535_priv {  	unsigned int sysclk; +	enum snd_soc_control_type control_type; +	void *control_data;  };  /* @@ -313,8 +313,7 @@ static int ak4535_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);  	u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);  	int rate = params_rate(params), fs = 256; @@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute)  static int ak4535_set_bias_level(struct snd_soc_codec *codec,  	enum snd_soc_bias_level level)  { -	u16 i; +	u16 i, mute_reg;  	switch (level) {  	case SND_SOC_BIAS_ON: -		ak4535_mute(codec->dai, 0); +		mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; +		ak4535_write(codec, AK4535_DAC, mute_reg);  		break;  	case SND_SOC_BIAS_PREPARE: -		ak4535_mute(codec->dai, 1); +		mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; +		ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);  		break;  	case SND_SOC_BIAS_STANDBY:  		i = ak4535_read_reg_cache(codec, AK4535_PM1); @@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = {  	.set_sysclk	= ak4535_set_dai_sysclk,  }; -struct snd_soc_dai ak4535_dai = { -	.name = "AK4535", +static struct snd_soc_dai_driver ak4535_dai = { +	.name = "ak4535-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {  		.formats = SNDRV_PCM_FMTBIT_S16_LE,},  	.ops = &ak4535_dai_ops,  }; -EXPORT_SYMBOL_GPL(ak4535_dai); -static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) +static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int ak4535_resume(struct platform_device *pdev) +static int ak4535_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	ak4535_sync(codec);  	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -/* - * initialise the AK4535 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ak4535_init(struct snd_soc_device *socdev) +static int ak4535_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret = 0; +	struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); -	codec->name = "AK4535"; -	codec->owner = THIS_MODULE; -	codec->read = ak4535_read_reg_cache; -	codec->write = ak4535_write; -	codec->set_bias_level = ak4535_set_bias_level; -	codec->dai = &ak4535_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(ak4535_reg); -	codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL); - -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "ak4535: failed to create pcms\n"); -		goto pcm_err; -	} +	codec->control_data = ak4535->control_data;  	/* power on device */  	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev)  				ARRAY_SIZE(ak4535_snd_controls));  	ak4535_add_widgets(codec); -	return ret; - -pcm_err: -	kfree(codec->reg_cache); +	return 0; +} -	return ret; +/* power down chip */ +static int ak4535_remove(struct snd_soc_codec *codec) +{ +	ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -static struct snd_soc_device *ak4535_socdev; +static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { +	.probe =	ak4535_probe, +	.remove =	ak4535_remove, +	.suspend =	ak4535_suspend, +	.resume =	ak4535_resume, +	.read = ak4535_read_reg_cache, +	.write = ak4535_write, +	.set_bias_level = ak4535_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(ak4535_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default = ak4535_reg, +};  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -static int ak4535_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = ak4535_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct ak4535_priv *ak4535;  	int ret; -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; +	ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); +	if (ak4535 == NULL) +		return -ENOMEM; -	ret = ak4535_init(socdev); -	if (ret < 0) -		printk(KERN_ERR "failed to initialise AK4535\n"); +	i2c_set_clientdata(i2c, ak4535); +	ak4535->control_data = i2c; +	ak4535->control_type = SND_SOC_I2C; +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_ak4535, &ak4535_dai, 1); +	if (ret < 0) +		kfree(ak4535);  	return ret;  } -static int ak4535_i2c_remove(struct i2c_client *client) +static __devexit int ak4535_i2c_remove(struct i2c_client *client)  { -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);  static struct i2c_driver ak4535_i2c_driver = {  	.driver = { -		.name = "AK4535 I2C Codec", +		.name = "ak4535-codec",  		.owner = THIS_MODULE,  	},  	.probe =    ak4535_i2c_probe, -	.remove =   ak4535_i2c_remove, +	.remove =   __devexit_p(ak4535_i2c_remove),  	.id_table = ak4535_i2c_id,  }; - -static int ak4535_add_i2c_device(struct platform_device *pdev, -				 const struct ak4535_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&ak4535_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "ak4535", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -			setup->i2c_bus); -		goto err_driver; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -			(unsigned int)info.addr); -		goto err_driver; -	} - -	return 0; - -err_driver: -	i2c_del_driver(&ak4535_i2c_driver); -	return -ENODEV; -}  #endif -static int ak4535_probe(struct platform_device *pdev) +static int __init ak4535_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct ak4535_setup_data *setup; -	struct snd_soc_codec *codec; -	struct ak4535_priv *ak4535; -	int ret; - -	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); - -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; - -	ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); -	if (ak4535 == NULL) { -		kfree(codec); -		return -ENOMEM; -	} - -	snd_soc_codec_set_drvdata(codec, ak4535); -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	ak4535_socdev = socdev; -	ret = -ENODEV; - +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		codec->hw_write = (hw_write_t)i2c_master_send; -		ret = ak4535_add_i2c_device(pdev, setup); -	} -#endif - +	ret = i2c_add_driver(&ak4535_i2c_driver);  	if (ret != 0) { -		kfree(snd_soc_codec_get_drvdata(codec)); -		kfree(codec); +		printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n", +		       ret);  	} +#endif  	return ret;  } +module_init(ak4535_modinit); -/* power down chip */ -static int ak4535_remove(struct platform_device *pdev) +static void __exit ak4535_exit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev);  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (codec->control_data) -		i2c_unregister_device(codec->control_data);  	i2c_del_driver(&ak4535_i2c_driver);  #endif -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ak4535 = { -	.probe = 	ak4535_probe, -	.remove = 	ak4535_remove, -	.suspend = 	ak4535_suspend, -	.resume =	ak4535_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); - -static int __init ak4535_modinit(void) -{ -	return snd_soc_register_dai(&ak4535_dai); -} -module_init(ak4535_modinit); - -static void __exit ak4535_exit(void) -{ -	snd_soc_unregister_dai(&ak4535_dai);  }  module_exit(ak4535_exit); diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h index c7a58703ea39..0431e5f634a2 100644 --- a/sound/soc/codecs/ak4535.h +++ b/sound/soc/codecs/ak4535.h @@ -36,12 +36,4 @@  #define AK4535_CACHEREGNUM 	0x10 -struct ak4535_setup_data { -	int            i2c_bus; -	unsigned short i2c_address; -}; - -extern struct snd_soc_dai ak4535_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4535; -  #endif diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3d7dc55305ec..31b35e967398 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -30,8 +30,6 @@  #include <sound/initval.h>  #include <sound/tlv.h> -#include "ak4642.h" -  #define AK4642_VERSION "0.0.1"  #define PW_MGMT1	0x00 @@ -102,7 +100,6 @@  #define FS3		(1 << 5)  #define FS_MASK		(FS0 | FS1 | FS2 | FS3) -struct snd_soc_codec_device soc_codec_dev_ak4642;  /*   * Playback Volume (table 39) @@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {  /* codec private data */  struct ak4642_priv { -	struct snd_soc_codec codec; +	unsigned int sysclk; +	enum snd_soc_control_type control_type; +	void *control_data;  }; -static struct snd_soc_codec *ak4642_codec; -  /*   * ak4642 register cache   */ @@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {  	.hw_params	= ak4642_dai_hw_params,  }; -struct snd_soc_dai ak4642_dai = { -	.name = "AK4642", +static struct snd_soc_dai_driver ak4642_dai = { +	.name = "ak4642-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = {  	.ops = &ak4642_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(ak4642_dai); -static int ak4642_resume(struct platform_device *pdev) +static int ak4642_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	ak4642_sync(codec);  	return 0;  } -/* - * initialise the AK4642 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ak4642_init(struct ak4642_priv *ak4642) + +static int ak4642_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = &ak4642->codec; -	int ret = 0; +	struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); -	if (ak4642_codec) { -		dev_err(codec->dev, "Another ak4642 is registered\n"); -		return -EINVAL; -	} +	dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, ak4642); -	codec->name		= "AK4642"; -	codec->owner		= THIS_MODULE; -	codec->read		= ak4642_read_reg_cache; -	codec->write		= ak4642_write; -	codec->dai		= &ak4642_dai; -	codec->num_dai		= 1;  	codec->hw_write		= (hw_write_t)i2c_master_send; -	codec->reg_cache_size	= ARRAY_SIZE(ak4642_reg); -	codec->reg_cache	= kmemdup(ak4642_reg, -					  sizeof(ak4642_reg), GFP_KERNEL); - -	if (!codec->reg_cache) -		return -ENOMEM; - -	ak4642_dai.dev = codec->dev; -	ak4642_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto reg_cache_err; -	} +	codec->control_data = ak4642->control_data; -	ret = snd_soc_register_dai(&ak4642_dai); -	if (ret) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		goto reg_cache_err; -	} - -	return ret; - -reg_cache_err: -	kfree(codec->reg_cache); -	codec->reg_cache = NULL; -	return ret; +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { +	.probe =	ak4642_probe, +	.resume =	ak4642_resume, +	.read		= ak4642_read_reg_cache, +	.write		= ak4642_write, +	.reg_cache_size	= ARRAY_SIZE(ak4642_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default	= ak4642_reg, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int ak4642_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  {  	struct ak4642_priv *ak4642; -	struct snd_soc_codec *codec;  	int ret;  	ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); -	if (!ak4642) +	if (ak4642 == NULL)  		return -ENOMEM; -	codec = &ak4642->codec; -	codec->dev = &i2c->dev; -  	i2c_set_clientdata(i2c, ak4642); -	codec->control_data = i2c; +	ak4642->control_data = i2c; +	ak4642->control_type = SND_SOC_I2C; -	ret = ak4642_init(ak4642); -	if (ret < 0) { -		printk(KERN_ERR "failed to initialise AK4642\n"); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_ak4642, &ak4642_dai, 1); +	if (ret < 0)  		kfree(ak4642); -	} -  	return ret;  } -static int ak4642_i2c_remove(struct i2c_client *client) +static __devexit int ak4642_i2c_remove(struct i2c_client *client)  { -	struct ak4642_priv *ak4642 = i2c_get_clientdata(client); - -	snd_soc_unregister_dai(&ak4642_dai); -	snd_soc_unregister_codec(&ak4642->codec); -	kfree(ak4642->codec.reg_cache); -	kfree(ak4642); -	ak4642_codec = NULL; - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);  static struct i2c_driver ak4642_i2c_driver = {  	.driver = { -		.name = "AK4642 I2C Codec", +		.name = "ak4642-codec",  		.owner = THIS_MODULE,  	}, -	.probe		= ak4642_i2c_probe, -	.remove		= ak4642_i2c_remove, -	.id_table	= ak4642_i2c_id, +	.probe =    ak4642_i2c_probe, +	.remove =   __devexit_p(ak4642_i2c_remove), +	.id_table = ak4642_i2c_id,  }; -  #endif -static int ak4642_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	int ret; - -	if (!ak4642_codec) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = ak4642_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "ak4642: failed to create pcms\n"); -		goto pcm_err; -	} - -	snd_soc_add_controls(ak4642_codec, ak4642_snd_controls, -			     ARRAY_SIZE(ak4642_snd_controls)); - -	dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); -	return ret; - -pcm_err: -	return ret; - -} - -/* power down chip */ -static int ak4642_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_ak4642 = { -	.probe =	ak4642_probe, -	.remove =	ak4642_remove, -	.resume =	ak4642_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); -  static int __init ak4642_modinit(void)  {  	int ret = 0; diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h deleted file mode 100644 index e476833d314e..000000000000 --- a/sound/soc/codecs/ak4642.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * ak4642.h  --  AK4642 Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto <morimoto.kuninori@renesas.com> - * - * Based on ak4535.c - * - * 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 _AK4642_H -#define _AK4642_H - -extern struct snd_soc_dai ak4642_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4642; - -#endif diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 87566932a3b1..239f0562003c 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -23,11 +23,11 @@  #include "ak4671.h" -static struct snd_soc_codec *ak4671_codec;  /* codec private data */  struct ak4671_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	u8 reg_cache[AK4671_CACHEREGNUM];  }; @@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {  	.set_fmt	= ak4671_set_dai_fmt,  }; -struct snd_soc_dai ak4671_dai = { -	.name = "AK4671", +static struct snd_soc_dai_driver ak4671_dai = { +	.name = "ak4671-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = {  		.formats = AK4671_FORMATS,},  	.ops = &ak4671_dai_ops,  }; -EXPORT_SYMBOL_GPL(ak4671_dai); -static int ak4671_probe(struct platform_device *pdev) +static int ak4671_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (ak4671_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} +	struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); +	int ret; -	socdev->card->codec = ak4671_codec; -	codec = ak4671_codec; +	codec->hw_write = (hw_write_t)i2c_master_send; +	codec->bias_level = SND_SOC_BIAS_OFF; -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);  	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto pcm_err; +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	}  	snd_soc_add_controls(codec, ak4671_snd_controls, @@ -665,121 +657,48 @@ static int ak4671_probe(struct platform_device *pdev)  	ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return ret; - -pcm_err: -	return ret;  } -static int ak4671_remove(struct platform_device *pdev) +static int ak4671_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - +	ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_ak4671 = { +static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {  	.probe = ak4671_probe,  	.remove = ak4671_remove, +	.set_bias_level = ak4671_set_bias_level, +	.reg_cache_size = AK4671_CACHEREGNUM, +	.reg_word_size = sizeof(u8), +	.reg_cache_default = ak4671_reg,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); - -static int ak4671_register(struct ak4671_priv *ak4671, -		enum snd_soc_control_type control) -{ -	int ret; -	struct snd_soc_codec *codec = &ak4671->codec; - -	if (ak4671_codec) { -		dev_err(codec->dev, "Another AK4671 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec,  ak4671); -	codec->name = "AK4671"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = ak4671_set_bias_level; -	codec->dai = &ak4671_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = AK4671_CACHEREGNUM; -	codec->reg_cache = &ak4671->reg_cache; - -	memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} - -	ak4671_dai.dev = codec->dev; -	ak4671_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&ak4671_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(ak4671); -	return ret; -} - -static void ak4671_unregister(struct ak4671_priv *ak4671) -{ -	ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&ak4671_dai); -	snd_soc_unregister_codec(&ak4671->codec); -	kfree(ak4671); -	ak4671_codec = NULL; -}  static int __devinit ak4671_i2c_probe(struct i2c_client *client,  		const struct i2c_device_id *id)  {  	struct ak4671_priv *ak4671; -	struct snd_soc_codec *codec; +	int ret;  	ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);  	if (ak4671 == NULL)  		return -ENOMEM; -	codec = &ak4671->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(client, ak4671); -	codec->control_data = client; - -	codec->dev = &client->dev; +	ak4671->control_data = client; +	ak4671->control_type = SND_SOC_I2C; -	return ak4671_register(ak4671, SND_SOC_I2C); +	ret = snd_soc_register_codec(&client->dev, +			&soc_codec_dev_ak4671, &ak4671_dai, 1); +	if (ret < 0) +		kfree(ak4671); +	return ret;  }  static __devexit int ak4671_i2c_remove(struct i2c_client *client)  { -	struct ak4671_priv *ak4671 = i2c_get_clientdata(client); - -	ak4671_unregister(ak4671); - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);  static struct i2c_driver ak4671_i2c_driver = {  	.driver = { -		.name = "ak4671", +		.name = "ak4671-codec",  		.owner = THIS_MODULE,  	},  	.probe = ak4671_i2c_probe, diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index e2fad964e88b..61cb7ab7552c 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h @@ -150,7 +150,4 @@  /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */  #define AK4671_MUTEN				0x04 -extern struct snd_soc_dai ak4671_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4671; -  #endif diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index a320fb5a0e26..823643932dde 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -30,6 +30,7 @@  #include <linux/slab.h>  #include <linux/clk.h>  #include <linux/mfd/davinci_voicecodec.h> +#include <linux/spi/spi.h>  #include <sound/core.h>  #include <sound/pcm.h> @@ -41,8 +42,6 @@  #include <mach/dm365.h> -#include "cq93vc.h" -  static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,  						unsigned int reg)  { @@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {  	.set_sysclk	= cq93vc_set_dai_sysclk,  }; -struct snd_soc_dai cq93vc_dai = { -	.name = "CQ93VC", +static struct snd_soc_dai_driver cq93vc_dai = { +	.name = "cq93vc-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {  		.formats = CQ93VC_FORMATS,},  	.ops = &cq93vc_dai_ops,  }; -EXPORT_SYMBOL_GPL(cq93vc_dai); -static int cq93vc_resume(struct platform_device *pdev) +static int cq93vc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -static struct snd_soc_codec *cq93vc_codec; - -static int cq93vc_probe(struct platform_device *pdev) +static int cq93vc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct device *dev = &pdev->dev; -	struct snd_soc_codec *codec; -	int ret; - -	socdev->card->codec = cq93vc_codec; -	codec = socdev->card->codec; - -	/* Register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(dev, "%s: failed to create pcms\n", pdev->name); -		return ret; -	} +	struct davinci_vc *davinci_vc = codec->dev->platform_data; + +	davinci_vc->cq93vc.codec = codec; +	codec->control_data = davinci_vc;  	/* Set controls */  	snd_soc_add_controls(codec, cq93vc_snd_controls, @@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)  	return 0;  } -static int cq93vc_remove(struct platform_device *pdev) +static int cq93vc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_cq93vc = { +static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { +	.read = cq93vc_read, +	.write = cq93vc_write, +	.set_bias_level = cq93vc_set_bias_level,  	.probe = cq93vc_probe,  	.remove = cq93vc_remove,  	.resume = cq93vc_resume,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc); -static __init int cq93vc_codec_probe(struct platform_device *pdev) +static int cq93vc_platform_probe(struct platform_device *pdev)  { -	struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) { -		dev_dbg(davinci_vc->dev, -			"could not allocate memory for codec data\n"); -		return -ENOMEM; -	} - -	davinci_vc->cq93vc.codec = codec; - -	cq93vc_dai.dev = &pdev->dev; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	codec->dev = &pdev->dev; -	codec->name = "CQ93VC"; -	codec->owner = THIS_MODULE; -	codec->read = cq93vc_read; -	codec->write = cq93vc_write; -	codec->set_bias_level = cq93vc_set_bias_level; -	codec->dai = &cq93vc_dai; -	codec->num_dai = 1; -	codec->control_data = davinci_vc; - -	cq93vc_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret) { -		dev_err(davinci_vc->dev, "failed to register codec\n"); -		goto fail1; -	} - -	ret = snd_soc_register_dai(&cq93vc_dai); -	if (ret) { -		dev_err(davinci_vc->dev, "could register dai\n"); -		goto fail2; -	} -	return 0; - -fail2: -	snd_soc_unregister_codec(codec); - -fail1: -	kfree(codec); -	cq93vc_codec = NULL; - -	return ret; +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_cq93vc, &cq93vc_dai, 1);  } -static int __devexit cq93vc_codec_remove(struct platform_device *pdev) +static int cq93vc_platform_remove(struct platform_device *pdev)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	snd_soc_unregister_dai(&cq93vc_dai); -	snd_soc_unregister_codec(&codec); - -	kfree(codec); -	cq93vc_codec = NULL; - +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  }  static struct platform_driver cq93vc_codec_driver = {  	.driver = { -		   .name = "cq93vc", -		   .owner = THIS_MODULE, -		   }, -	.probe = cq93vc_codec_probe, -	.remove = __devexit_p(cq93vc_codec_remove), +			.name = "cq93vc-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = cq93vc_platform_probe, +	.remove = __devexit_p(cq93vc_platform_remove),  }; -static __init int cq93vc_init(void) +static int __init cq93vc_init(void)  { -	return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe); +	return platform_driver_register(&cq93vc_codec_driver);  }  module_init(cq93vc_init); -static __exit void cq93vc_exit(void) +static void __exit cq93vc_exit(void)  {  	platform_driver_unregister(&cq93vc_codec_driver);  } diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h deleted file mode 100644 index 845b1968ef9c..000000000000 --- a/sound/soc/codecs/cq93vc.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms - * - * Copyright (C) 2010 Texas Instruments, Inc - * - * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CQ93VC_H -#define _CQ93VC_H - -extern struct snd_soc_dai cq93vc_dai; -extern struct snd_soc_codec_device soc_codec_dev_cq93vc; - -#endif diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 30d949239def..6542dc038951 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -31,8 +31,6 @@  #include <linux/delay.h>  #include <linux/regulator/consumer.h> -#include "cs4270.h" -  /*   * The codec isn't really big-endian or little-endian, since the I2S   * interface requires data to be sent serially with the MSbit first. @@ -114,7 +112,8 @@ static const char *supply_names[] = {  /* Private data for the CS4270 */  struct cs4270_private { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	u8 reg_cache[CS4270_NUMREGS];  	unsigned int mclk; /* Input frequency of the MCLK pin */  	unsigned int mode; /* The mode (I2S or left-justified) */ @@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,  {  	struct snd_soc_codec *codec = codec_dai->codec;  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); -	unsigned int rates = 0; -	unsigned int rate_min = -1; -	unsigned int rate_max = 0; -	unsigned int i;  	cs4270->mclk = freq; - -	if (cs4270->mclk) { -		for (i = 0; i < NUM_MCLK_RATIOS; i++) { -			unsigned int rate = freq / cs4270_mode_ratios[i].ratio; -			rates |= snd_pcm_rate_to_rate_bit(rate); -			if (rate < rate_min) -				rate_min = rate; -			if (rate > rate_max) -				rate_max = rate; -		} -		/* FIXME: soc should support a rate list */ -		rates &= ~SNDRV_PCM_RATE_KNOT; - -		if (!rates) { -			dev_err(codec->dev, "could not find a valid sample rate\n"); -			return -EINVAL; -		} -	} else { -		/* enable all possible rates */ -		rates = SNDRV_PCM_RATE_8000_192000; -		rate_min = 8000; -		rate_max = 192000; -	} - -	codec_dai->playback.rates = rates; -	codec_dai->playback.rate_min = rate_min; -	codec_dai->playback.rate_max = rate_max; - -	codec_dai->capture.rates = rates; -	codec_dai->capture.rate_min = rate_min; -	codec_dai->capture.rate_max = rate_max; -  	return 0;  } @@ -410,8 +373,7 @@ static int cs4270_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);  	int ret;  	unsigned int i; @@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {  		snd_soc_get_volsw, cs4270_soc_put_mute),  }; -/* - * cs4270_codec - global variable to store codec for the ASoC probe function - * - * If struct i2c_driver had a private_data field, we wouldn't need to use - * cs4270_codec.  This is the only way to pass the codec structure from - * cs4270_i2c_probe() to cs4270_probe().  Unfortunately, there is no good - * way to synchronize these two functions.  cs4270_i2c_probe() can be called - * multiple times before cs4270_probe() is called even once.  So for now, we - * also only allow cs4270_i2c_probe() to be run once.  That means that we do - * not support more than one cs4270 device in the system, at least for now. - */ -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, @@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {  	.digital_mute	= cs4270_dai_mute,  }; -struct snd_soc_dai cs4270_dai = { -	.name = "cs4270", +struct snd_soc_dai_driver cs4270_dai = { +	.name = "cs4270-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1,  		.channels_max = 2, -		.rates = 0, +		.rates = SNDRV_PCM_RATE_CONTINUOUS, +		.rate_min = 4000, +		.rate_max = 216000,  		.formats = CS4270_FORMATS,  	},  	.capture = {  		.stream_name = "Capture",  		.channels_min = 1,  		.channels_max = 2, -		.rates = 0, +		.rates = SNDRV_PCM_RATE_CONTINUOUS, +		.rate_min = 4000, +		.rate_max = 216000,  		.formats = CS4270_FORMATS,  	},  	.ops = &cs4270_dai_ops, @@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);   * This function is called when ASoC has all the pieces it needs to   * instantiate a sound driver.   */ -static int cs4270_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = cs4270_codec; -	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); -	int i, 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; -	} - -	/* Add the non-DAPM controls */ -	ret = snd_soc_add_controls(codec, cs4270_snd_controls, -				ARRAY_SIZE(cs4270_snd_controls)); -	if (ret < 0) { -		dev_err(codec->dev, "failed to add controls\n"); -		goto error_free_pcms; -	} - -	/* get the power supply regulators */ -	for (i = 0; i < ARRAY_SIZE(supply_names); i++) -		cs4270->supplies[i].supply = supply_names[i]; - -	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), -				 cs4270->supplies); -	if (ret < 0) -		goto error_free_pcms; - -	ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), -				    cs4270->supplies); -	if (ret < 0) -		goto error_free_regulators; - -	return 0; - -error_free_regulators: -	regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), -			    cs4270->supplies); - -error_free_pcms: -	snd_soc_free_pcms(socdev); - -	return ret; -} - -/** - * cs4270_remove - ASoC remove function - * @pdev: platform device - * - * This function is the counterpart to cs4270_probe(). - */ -static int cs4270_remove(struct platform_device *pdev) +static int cs4270_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = cs4270_codec;  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); +	int i, ret, reg; -	snd_soc_free_pcms(socdev); -	regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); -	regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - -	return 0; -}; - -/** - * cs4270_i2c_probe - initialize the I2C interface of the CS4270 - * @i2c_client: the I2C client object - * @id: the I2C device ID (ignored) - * - * This function is called whenever the I2C subsystem finds a device that - * matches the device ID given via a prior call to i2c_add_driver(). - */ -static int cs4270_i2c_probe(struct i2c_client *i2c_client, -	const struct i2c_device_id *id) -{ -	struct snd_soc_codec *codec; -	struct cs4270_private *cs4270; -	unsigned int reg; -	int ret; - -	/* For now, we only support one cs4270 device in the system.  See the -	 * comment for cs4270_codec. -	 */ -	if (cs4270_codec) { -		dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", -		       i2c_client->addr); -		dev_err(&i2c_client->dev, "only one per board allowed\n"); -		/* Should we return something other than ENODEV here? */ -		return -ENODEV; -	} - -	/* Verify that we have a CS4270 */ - -	ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); -	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", -		       i2c_client->addr); -		return ret; -	} -	/* The top four bits of the chip ID should be 1100. */ -	if ((ret & 0xF0) != 0xC0) { -		dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", -		       i2c_client->addr); -		return -ENODEV; -	} - -	dev_info(&i2c_client->dev, "found device at i2c address %X\n", -		i2c_client->addr); -	dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); - -	/* Allocate enough space for the snd_soc_codec structure -	   and our private data together. */ -	cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); -	if (!cs4270) { -		dev_err(&i2c_client->dev, "could not allocate codec\n"); -		return -ENOMEM; -	} -	codec = &cs4270->codec; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->dev = &i2c_client->dev; -	codec->name = "CS4270"; -	codec->owner = THIS_MODULE; -	codec->dai = &cs4270_dai; -	codec->num_dai = 1; -	snd_soc_codec_set_drvdata(codec, cs4270); -	codec->control_data = i2c_client; -	codec->read = cs4270_read_reg_cache; -	codec->write = cs4270_i2c_write; -	codec->reg_cache = cs4270->reg_cache; -	codec->reg_cache_size = CS4270_NUMREGS; +	codec->control_data = cs4270->control_data;  	/* The I2C interface is set up, so pre-fill our register cache */  	ret = cs4270_fill_cache(codec);  	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to fill register cache\n"); -		goto error_free_codec; +		dev_err(codec->dev, "failed to fill register cache\n"); +		return ret;  	}  	/* Disable auto-mute.  This feature appears to be buggy.  In some @@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,  	reg &= ~CS4270_MUTE_AUTO;  	ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);  	if (ret < 0) { -		dev_err(&i2c_client->dev, "i2c write failed\n"); +		dev_err(codec->dev, "i2c write failed\n");  		return ret;  	} @@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,  	reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);  	ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);  	if (ret < 0) { -		dev_err(&i2c_client->dev, "i2c write failed\n"); +		dev_err(codec->dev, "i2c write failed\n");  		return ret;  	} -	/* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI -	 * structure for each CS4270 device, but the machine driver needs to -	 * have a pointer to the DAI structure, so for now it must be a global -	 * variable. -	 */ -	cs4270_dai.dev = &i2c_client->dev; - -	/* Register the DAI.  If all the other ASoC driver have already -	 * registered, then this will call our probe function, so -	 * cs4270_codec needs to be ready. -	 */ -	cs4270_codec = codec; -	ret = snd_soc_register_dai(&cs4270_dai); +	/* Add the non-DAPM controls */ +	ret = snd_soc_add_controls(codec, cs4270_snd_controls, +				ARRAY_SIZE(cs4270_snd_controls));  	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to register DAIe\n"); -		goto error_free_codec; +		dev_err(codec->dev, "failed to add controls\n"); +		return ret;  	} -	i2c_set_clientdata(i2c_client, cs4270); +	/* get the power supply regulators */ +	for (i = 0; i < ARRAY_SIZE(supply_names); i++) +		cs4270->supplies[i].supply = supply_names[i]; + +	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), +				 cs4270->supplies); +	if (ret < 0) +		return ret; + +	ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), +				    cs4270->supplies); +	if (ret < 0) +		goto error_free_regulators;  	return 0; -error_free_codec: -	kfree(cs4270); -	cs4270_codec = NULL; -	cs4270_dai.dev = NULL; +error_free_regulators: +	regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), +			    cs4270->supplies);  	return ret;  }  /** - * cs4270_i2c_remove - remove an I2C device - * @i2c_client: the I2C client object + * cs4270_remove - ASoC remove function + * @pdev: platform device   * - * This function is the counterpart to cs4270_i2c_probe(). + * This function is the counterpart to cs4270_probe().   */ -static int cs4270_i2c_remove(struct i2c_client *i2c_client) +static int cs4270_remove(struct snd_soc_codec *codec)  { -	struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); +	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); -	kfree(cs4270); -	cs4270_codec = NULL; -	cs4270_dai.dev = NULL; +	regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); +	regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);  	return 0; -} - -/* - * cs4270_id - I2C device IDs supported by this driver - */ -static struct i2c_device_id cs4270_id[] = { -	{"cs4270", 0}, -	{}  }; -MODULE_DEVICE_TABLE(i2c, cs4270_id);  #ifdef CONFIG_PM @@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);   * and all registers are written back to the hardware when resuming.   */ -static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) +static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)  { -	struct snd_soc_codec *codec = cs4270_codec;  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);  	int reg, ret; @@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)  	return 0;  } -static int cs4270_soc_resume(struct platform_device *pdev) +static int cs4270_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = cs4270_codec;  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);  	struct i2c_client *i2c_client = codec->control_data;  	int reg; @@ -896,6 +704,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)  #endif /* CONFIG_PM */  /* + * ASoC codec device structure + * + * Assign this variable to the codec_dev field of the machine driver's + * snd_soc_device structure. + */ +static struct snd_soc_codec_driver soc_codec_device_cs4270 = { +	.probe =	cs4270_probe, +	.remove =	cs4270_remove, +	.suspend =	cs4270_soc_suspend, +	.resume =	cs4270_soc_resume, +	.read = cs4270_read_reg_cache, +	.write = cs4270_i2c_write, +	.reg_cache_size = CS4270_NUMREGS, +	.reg_word_size = sizeof(u8), +}; + +/** + * cs4270_i2c_probe - initialize the I2C interface of the CS4270 + * @i2c_client: the I2C client object + * @id: the I2C device ID (ignored) + * + * This function is called whenever the I2C subsystem finds a device that + * matches the device ID given via a prior call to i2c_add_driver(). + */ +static int cs4270_i2c_probe(struct i2c_client *i2c_client, +	const struct i2c_device_id *id) +{ +	struct cs4270_private *cs4270; +	int ret; + +	/* Verify that we have a CS4270 */ + +	ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); +	if (ret < 0) { +		dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", +		       i2c_client->addr); +		return ret; +	} +	/* The top four bits of the chip ID should be 1100. */ +	if ((ret & 0xF0) != 0xC0) { +		dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", +		       i2c_client->addr); +		return -ENODEV; +	} + +	dev_info(&i2c_client->dev, "found device at i2c address %X\n", +		i2c_client->addr); +	dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); + +	cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); +	if (!cs4270) { +		dev_err(&i2c_client->dev, "could not allocate codec\n"); +		return -ENOMEM; +	} + +	i2c_set_clientdata(i2c_client, cs4270); +	cs4270->control_data = i2c_client; +	cs4270->control_type = SND_SOC_I2C; + +	ret = snd_soc_register_codec(&i2c_client->dev, +			&soc_codec_device_cs4270, &cs4270_dai, 1); +	if (ret < 0) +		kfree(cs4270); +	return ret; +} + +/** + * cs4270_i2c_remove - remove an I2C device + * @i2c_client: the I2C client object + * + * This function is the counterpart to cs4270_i2c_probe(). + */ +static int cs4270_i2c_remove(struct i2c_client *i2c_client) +{ +	snd_soc_unregister_codec(&i2c_client->dev); +	kfree(i2c_get_clientdata(i2c_client)); +	return 0; +} + +/* + * cs4270_id - I2C device IDs supported by this driver + */ +static struct i2c_device_id cs4270_id[] = { +	{"cs4270", 0}, +	{} +}; +MODULE_DEVICE_TABLE(i2c, cs4270_id); + +/*   * cs4270_i2c_driver - I2C device identification   *   * This structure tells the I2C subsystem how to identify and support a @@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)   */  static struct i2c_driver cs4270_i2c_driver = {  	.driver = { -		.name = "cs4270", +		.name = "cs4270-codec",  		.owner = THIS_MODULE,  	},  	.id_table = cs4270_id, @@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = {  	.remove = cs4270_i2c_remove,  }; -/* - * ASoC codec device structure - * - * Assign this variable to the codec_dev field of the machine driver's - * snd_soc_device structure. - */ -struct snd_soc_codec_device soc_codec_device_cs4270 = { -	.probe = 	cs4270_probe, -	.remove = 	cs4270_remove, -	.suspend =	cs4270_soc_suspend, -	.resume =	cs4270_soc_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); -  static int __init cs4270_init(void)  {  	pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h deleted file mode 100644 index adc6cd9667d4..000000000000 --- a/sound/soc/codecs/cs4270.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Cirrus Logic CS4270 ALSA SoC Codec Driver - * - * Author: Timur Tabi <timur@freescale.com> - * - * Copyright 2007 Freescale Semiconductor, Inc.  This file is licensed under - * the terms of the GNU General Public License version 2.  This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef _CS4270_H -#define _CS4270_H - -/* - * The ASoC codec DAI structure for the CS4270.  Assign this structure to - * the .codec_dai field of your machine driver's snd_soc_dai_link structure. - */ -extern struct snd_soc_dai cs4270_dai; - -/* - * The ASoC codec device structure for the CS4270.  Assign this structure - * to the .codec_dev field of your machine driver's snd_soc_device - * structure. - */ -extern struct snd_soc_codec_device soc_codec_device_cs4270; - -#endif diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index dd9b8550c402..8a25743870c2 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -42,15 +42,14 @@ enum master_slave_mode {  };  struct cs42l51_private { +	enum snd_soc_control_type control_type; +	void *control_data;  	unsigned int mclk;  	unsigned int audio_mode;	/* The mode (I2S or left-justified) */  	enum master_slave_mode func; -	struct snd_soc_codec codec;  	u8 reg_cache[CS42L51_NUMREGS];  }; -static struct snd_soc_codec *cs42l51_codec; -  #define CS42L51_FORMATS ( \  		SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \  		SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ @@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec)  	return 0;  } -static int cs42l51_i2c_probe(struct i2c_client *i2c_client, -	const struct i2c_device_id *id) -{ -	struct snd_soc_codec *codec; -	struct cs42l51_private *cs42l51; -	int ret = 0; -	int reg; - -	if (cs42l51_codec) -		return -EBUSY; - -	/* Verify that we have a CS42L51 */ -	ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); -	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to read I2C\n"); -		goto error; -	} - -	if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && -	    (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { -		dev_err(&i2c_client->dev, "Invalid chip id\n"); -		ret = -ENODEV; -		goto error; -	} - -	dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", -				ret & 7); - -	cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); -	if (!cs42l51) { -		dev_err(&i2c_client->dev, "could not allocate codec\n"); -		return -ENOMEM; -	} -	codec = &cs42l51->codec; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->dev = &i2c_client->dev; -	codec->name = "CS42L51"; -	codec->owner = THIS_MODULE; -	codec->dai = &cs42l51_dai; -	codec->num_dai = 1; -	snd_soc_codec_set_drvdata(codec, cs42l51); - -	codec->control_data = i2c_client; -	codec->reg_cache = cs42l51->reg_cache; -	codec->reg_cache_size = CS42L51_NUMREGS; -	i2c_set_clientdata(i2c_client, codec); - -	ret = cs42l51_fill_cache(codec); -	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to fill register cache\n"); -		goto error_alloc; -	} - -	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); -	if (ret < 0) { -		dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret); -		goto error_alloc; -	} - -	/* -	 * DAC configuration -	 * - Use signal processor -	 * - auto mute -	 * - vol changes immediate -	 * - no de-emphasize -	 */ -	reg = CS42L51_DAC_CTL_DATA_SEL(1) -		| CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); -	ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); -	if (ret < 0) -		goto error_alloc; - -	cs42l51_dai.dev = codec->dev; -	cs42l51_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto error_alloc; -	} - -	ret = snd_soc_register_dai(&cs42l51_dai); -	if (ret < 0) { -		dev_err(&i2c_client->dev, "failed to register DAIe\n"); -		goto error_reg; -	} - -	return 0; - -error_reg: -	snd_soc_unregister_codec(codec); -error_alloc: -	kfree(cs42l51); -error: -	return ret; -} - -static int cs42l51_i2c_remove(struct i2c_client *client) -{ -	struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); -	snd_soc_unregister_dai(&cs42l51_dai); -	snd_soc_unregister_codec(cs42l51_codec); -	cs42l51_codec = NULL; -	kfree(cs42l51); -	return 0; -} - - -static const struct i2c_device_id cs42l51_id[] = { -	{"cs42l51", 0}, -	{} -}; -MODULE_DEVICE_TABLE(i2c, cs42l51_id); - -static struct i2c_driver cs42l51_i2c_driver = { -	.driver = { -		.name = "CS42L51 I2C", -		.owner = THIS_MODULE, -	}, -	.id_table = cs42l51_id, -	.probe = cs42l51_i2c_probe, -	.remove = cs42l51_i2c_remove, -}; -  static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,  			struct snd_ctl_elem_value *ucontrol)  { @@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,  {  	struct snd_soc_codec *codec = codec_dai->codec;  	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); -	struct cs42l51_ratios *ratios = NULL; -	int nr_ratios = 0; -	unsigned int rates = 0; -	unsigned int rate_min = -1; -	unsigned int rate_max = 0; -	int i;  	cs42l51->mclk = freq; - -	switch (cs42l51->func) { -	case MODE_MASTER: -		return -EINVAL; -	case MODE_SLAVE: -		ratios = slave_ratios; -		nr_ratios = ARRAY_SIZE(slave_ratios); -		break; -	case MODE_SLAVE_AUTO: -		ratios = slave_auto_ratios; -		nr_ratios = ARRAY_SIZE(slave_auto_ratios); -		break; -	} - -	for (i = 0; i < nr_ratios; i++) { -		unsigned int rate = freq / ratios[i].ratio; -		rates |= snd_pcm_rate_to_rate_bit(rate); -		if (rate < rate_min) -			rate_min = rate; -		if (rate > rate_max) -			rate_max = rate; -	} -	rates &= ~SNDRV_PCM_RATE_KNOT; - -	if (!rates) { -		dev_err(codec->dev, "could not find a valid sample rate\n"); -		return -EINVAL; -	} - -	codec_dai->playback.rates = rates; -	codec_dai->playback.rate_min = rate_min; -	codec_dai->playback.rate_max = rate_max; - -	codec_dai->capture.rates = rates; -	codec_dai->capture.rate_min = rate_min; -	codec_dai->capture.rate_max = rate_max; -  	return 0;  } @@ -537,8 +365,7 @@ static int cs42l51_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);  	int ret;  	unsigned int i; @@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {  	.digital_mute   = cs42l51_dai_mute,  }; -struct snd_soc_dai cs42l51_dai = { -	.name = "CS42L51 HiFi", +static struct snd_soc_dai_driver cs42l51_dai = { +	.name = "cs42l51-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {  	},  	.ops = &cs42l51_dai_ops,  }; -EXPORT_SYMBOL_GPL(cs42l51_dai); - -static int cs42l51_probe(struct platform_device *pdev) +static int cs42l51_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; +	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); +	int ret, reg; -	if (!cs42l51_codec) { -		dev_err(&pdev->dev, "CS42L51 codec not yet registered\n"); -		return -EINVAL; -	} +	codec->control_data = cs42l51->control_data; -	socdev->card->codec = cs42l51_codec; -	codec = socdev->card->codec; +	ret = cs42l51_fill_cache(codec); +	if (ret < 0) { +		dev_err(codec->dev, "failed to fill register cache\n"); +		return ret; +	} -	/* Register PCMs */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);  	if (ret < 0) { -		dev_err(&pdev->dev, "failed to create PCMs\n"); +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);  		return ret;  	} +	/* +	 * DAC configuration +	 * - Use signal processor +	 * - auto mute +	 * - vol changes immediate +	 * - no de-emphasize +	 */ +	reg = CS42L51_DAC_CTL_DATA_SEL(1) +		| CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); +	ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); +	if (ret < 0) +		return ret; +  	snd_soc_add_controls(codec, cs42l51_snd_controls,  		ARRAY_SIZE(cs42l51_snd_controls));  	snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, @@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)  	return 0;  } +static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { +	.probe =	cs42l51_probe, +	.reg_cache_size = CS42L51_NUMREGS, +	.reg_word_size = sizeof(u8), +}; -static int cs42l51_remove(struct platform_device *pdev) +static int cs42l51_i2c_probe(struct i2c_client *i2c_client, +	const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); +	struct cs42l51_private *cs42l51; +	int ret; -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	/* Verify that we have a CS42L51 */ +	ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); +	if (ret < 0) { +		dev_err(&i2c_client->dev, "failed to read I2C\n"); +		goto error; +	} + +	if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && +	    (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { +		dev_err(&i2c_client->dev, "Invalid chip id\n"); +		ret = -ENODEV; +		goto error; +	} + +	dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", +				ret & 7); + +	cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); +	if (!cs42l51) { +		dev_err(&i2c_client->dev, "could not allocate codec\n"); +		return -ENOMEM; +	} + +	i2c_set_clientdata(i2c_client, cs42l51); +	cs42l51->control_data = i2c_client; +	cs42l51->control_type = SND_SOC_I2C; +	ret =  snd_soc_register_codec(&i2c_client->dev, +			&soc_codec_device_cs42l51, &cs42l51_dai, 1); +	if (ret < 0) +		kfree(cs42l51); +error: +	return ret; +} + +static int cs42l51_i2c_remove(struct i2c_client *client) +{ +	struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); + +	snd_soc_unregister_codec(&client->dev); +	kfree(cs42l51);  	return 0;  } -struct snd_soc_codec_device soc_codec_device_cs42l51 = { -	.probe =	cs42l51_probe, -	.remove =	cs42l51_remove +static const struct i2c_device_id cs42l51_id[] = { +	{"cs42l51", 0}, +	{} +}; +MODULE_DEVICE_TABLE(i2c, cs42l51_id); + +static struct i2c_driver cs42l51_i2c_driver = { +	.driver = { +		.name = "cs42L51-codec", +		.owner = THIS_MODULE, +	}, +	.id_table = cs42l51_id, +	.probe = cs42l51_i2c_probe, +	.remove = cs42l51_i2c_remove,  }; -EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);  static int __init cs42l51_init(void)  { diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8f0bd9786ad2..2beeb171db4b 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -158,6 +158,4 @@  #define CS42L51_LASTREG		0x20  #define CS42L51_NUMREGS		(CS42L51_LASTREG - CS42L51_FIRSTREG + 1) -extern struct snd_soc_dai cs42l51_dai; -extern struct snd_soc_codec_device soc_codec_device_cs42l51;  #endif diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f07a415c753f..cf4323dbf9c4 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -24,7 +24,8 @@  struct cx20442_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	u8 reg_cache[1];  }; @@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,  {  	u8 *reg_cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	return reg_cache[reg]; @@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)  static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,  							unsigned int value)  { +	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);  	u8 *reg_cache = codec->reg_cache;  	int vls, vsp, old, len;  	char buf[18]; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EINVAL;  	/* hw_write and control_data pointers required for talking to the modem  	 * are expected to be set by the line discipline initialization code */ -	if (!codec->hw_write || !codec->control_data) +	if (!codec->hw_write || !cx20442->control_data)  		return -EIO;  	old = reg_cache[reg]; @@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,  		return -ENOMEM;  	dev_dbg(codec->dev, "%s: %s\n", __func__, buf); -	if (codec->hw_write(codec->control_data, buf, len) != len) +	if (codec->hw_write(cx20442->control_data, buf, len) != len)  		return -EIO;  	return 0;  } -/* Moved up here as line discipline referres it during initialization */ -static struct snd_soc_codec *cx20442_codec; - -  /*   * Line discpline related code   * @@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";  /* Line discipline .open() */  static int v253_open(struct tty_struct *tty)  { -	struct snd_soc_codec *codec = cx20442_codec;  	int ret, len = strlen(v253_init);  	/* Doesn't make sense without write callback */  	if (!tty->ops->write)  		return -EINVAL; -	/* Pass the codec structure address for use by other ldisc callbacks */ -	tty->disc_data = codec; +	/* Won't work if no codec pointer has been passed by a card driver */ +	if (!tty->disc_data) +		return -ENODEV;  	if (tty->ops->write(tty, v253_init, len) != len) {  		ret = -EIO; @@ -253,15 +251,18 @@ err:  static void v253_close(struct tty_struct *tty)  {  	struct snd_soc_codec *codec = tty->disc_data; +	struct cx20442_priv *cx20442;  	tty->disc_data = NULL;  	if (!codec)  		return; +	cx20442 = snd_soc_codec_get_drvdata(codec); +  	/* Prevent the codec driver from further accessing the modem */  	codec->hw_write = NULL; -	codec->control_data = NULL; +	cx20442->control_data = NULL;  	codec->pop_time = 0;  } @@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,  				const unsigned char *cp, char *fp, int count)  {  	struct snd_soc_codec *codec = tty->disc_data; +	struct cx20442_priv *cx20442;  	if (!codec)  		return; -	if (!codec->control_data) { +	cx20442 = snd_soc_codec_get_drvdata(codec); + +	if (!cx20442->control_data) {  		/* First modem response, complete setup procedure */  		/* Set up codec driver access to modem controls */ -		codec->control_data = tty; +		cx20442->control_data = tty;  		codec->hw_write = (hw_write_t)tty->ops->write;  		codec->pop_time = 1;  	} @@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);   * Codec DAI   */ -struct snd_soc_dai cx20442_dai = { -	.name = "CX20442", +static struct snd_soc_dai_driver cx20442_dai = { +	.name = "cx20442-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {  		.formats = SNDRV_PCM_FMTBIT_S16_LE,  	},  }; -EXPORT_SYMBOL_GPL(cx20442_dai); -static int cx20442_codec_probe(struct platform_device *pdev) +static int cx20442_codec_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	if (!cx20442_codec) { -		dev_err(&pdev->dev, "cx20442 not yet discovered\n"); -		return -ENODEV; -	} -	codec = cx20442_codec; - -	socdev->card->codec = codec; +	struct cx20442_priv *cx20442; -	/* 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; -	} +	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); +	if (cx20442 == NULL) +		return -ENOMEM; +	snd_soc_codec_set_drvdata(codec, cx20442);  	cx20442_add_widgets(codec); -pcm_err: -	return ret; +	cx20442->control_data = NULL; +	codec->hw_write = NULL; +	codec->pop_time = 0; + +	return 0;  }  /* power down chip */ -static int cx20442_codec_remove(struct platform_device *pdev) +static int cx20442_codec_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); +	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	if (cx20442->control_data) { +			struct tty_struct *tty = cx20442->control_data; +			tty_hangup(tty); +	} +	kfree(cx20442);  	return 0;  } -struct snd_soc_codec_device cx20442_codec_dev = { +static struct snd_soc_codec_driver cx20442_codec_dev = {  	.probe = 	cx20442_codec_probe,  	.remove = 	cx20442_codec_remove, +	.reg_cache_size = 1, +	.reg_word_size = sizeof(u8), +	.read = cx20442_read_reg_cache, +	.write = cx20442_write,  }; -EXPORT_SYMBOL_GPL(cx20442_codec_dev); - -static int cx20442_register(struct cx20442_priv *cx20442) -{ -	struct snd_soc_codec *codec = &cx20442->codec; -	int ret; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "CX20442"; -	codec->owner = THIS_MODULE; -	snd_soc_codec_set_drvdata(codec, cx20442); - -	codec->dai = &cx20442_dai; -	codec->num_dai = 1; - -	codec->reg_cache = &cx20442->reg_cache; -	codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); -	codec->read = cx20442_read_reg_cache; -	codec->write = cx20442_write; - -	codec->bias_level = SND_SOC_BIAS_OFF; - -	cx20442_dai.dev = codec->dev; - -	cx20442_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&cx20442_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	cx20442_codec = NULL; -	kfree(cx20442); -	return ret; -} - -static void cx20442_unregister(struct cx20442_priv *cx20442) -{ -	snd_soc_unregister_dai(&cx20442_dai); -	snd_soc_unregister_codec(&cx20442->codec); - -	cx20442_codec = NULL; -	kfree(cx20442); -}  static int cx20442_platform_probe(struct platform_device *pdev)  { -	struct cx20442_priv *cx20442; -	struct snd_soc_codec *codec; - -	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); -	if (cx20442 == NULL) -		return -ENOMEM; - -	codec = &cx20442->codec; - -	codec->control_data = NULL; -	codec->hw_write = NULL; -	codec->pop_time = 0; - -	codec->dev = &pdev->dev; -	platform_set_drvdata(pdev, cx20442); - -	return cx20442_register(cx20442); +	return snd_soc_register_codec(&pdev->dev, +			&cx20442_codec_dev, &cx20442_dai, 1);  }  static int __exit cx20442_platform_remove(struct platform_device *pdev)  { -	struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); - -	cx20442_unregister(cx20442); +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  }  static struct platform_driver cx20442_platform_driver = {  	.driver = { -		.name = "cx20442", +		.name = "cx20442-codec",  		.owner = THIS_MODULE,  		},  	.probe = cx20442_platform_probe, @@ -487,4 +412,4 @@ module_exit(cx20442_exit);  MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");  MODULE_AUTHOR("Janusz Krzysztofik");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442"); +MODULE_ALIAS("platform:cx20442-codec"); diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h index 688a5eb62e17..c7a7c79ef0cd 100644 --- a/sound/soc/codecs/cx20442.h +++ b/sound/soc/codecs/cx20442.h @@ -13,8 +13,6 @@  #ifndef _CX20442_CODEC_H  #define _CX20442_CODEC_H -extern struct snd_soc_dai cx20442_dai; -extern struct snd_soc_codec_device cx20442_codec_dev;  extern struct tty_ldisc_ops v253_ops;  #endif diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3c51d6a57523..eabf3c062500 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -25,8 +25,6 @@  #include <sound/initval.h>  #include <sound/tlv.h> -#include "da7210.h" -  /* DA7210 register space */  #define DA7210_STATUS			0x02  #define DA7210_STARTUP1			0x03 @@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {  /* Codec private data */  struct da7210_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  }; -static struct snd_soc_codec *da7210_codec; -  /*   * Register cache   */ @@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)  	u8 *cache = codec->reg_cache;  	u8 data[2]; -	BUG_ON(codec->volatile_register); +	BUG_ON(codec->driver->volatile_register);  	data[0] = reg & 0xff;  	data[1] = value & 0xff; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -EIO;  	if (2 != codec->hw_write(codec->control_data, data, 2)) @@ -267,8 +264,7 @@ static int da7210_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u32 dai_cfg1;  	u32 hpf_reg, hpf_mask, hpf_value;  	u32 fs, bypass; @@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {  	.set_fmt	= da7210_set_dai_fmt,  }; -struct snd_soc_dai da7210_dai = { -	.name = "DA7210 IIS", -	.id = 0, +static struct snd_soc_dai_driver da7210_dai = { +	.name = "da7210-hifi",  	/* playback capabilities */  	.playback = {  		.stream_name = "Playback", @@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {  	.ops = &da7210_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(da7210_dai); -/* - * Initialize the DA7210 driver - * register the mixer and dsp interfaces with the kernel - */ -static int da7210_init(struct da7210_priv *da7210) +static int da7210_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = &da7210->codec; -	int ret = 0; +	struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); -	if (da7210_codec) { -		dev_err(codec->dev, "Another da7210 is registered\n"); -		return -EINVAL; -	} +	dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, da7210); -	codec->name		= "DA7210"; -	codec->owner		= THIS_MODULE; -	codec->read		= da7210_read; -	codec->write		= da7210_write; -	codec->dai		= &da7210_dai; -	codec->num_dai		= 1; +	codec->control_data = da7210->control_data;  	codec->hw_write		= (hw_write_t)i2c_master_send; -	codec->reg_cache_size	= ARRAY_SIZE(da7210_reg); -	codec->reg_cache	= kmemdup(da7210_reg, -					  sizeof(da7210_reg), GFP_KERNEL); - -	if (!codec->reg_cache) -		return -ENOMEM; - -	da7210_dai.dev = codec->dev; -	da7210_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret) { -		dev_err(codec->dev, "Failed to register CODEC: %d\n", ret); -		goto init_err; -	} - -	ret = snd_soc_register_dai(&da7210_dai); -	if (ret) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto codec_err; -	}  	/* FIXME  	 * @@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)  	/* Activate all enabled subsystem */  	da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); -	return ret; - -codec_err: -	snd_soc_unregister_codec(codec); -init_err: -	kfree(codec->reg_cache); -	codec->reg_cache = NULL; +	snd_soc_add_controls(codec, da7210_snd_controls, +			     ARRAY_SIZE(da7210_snd_controls)); -	return ret; +	dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_da7210 = { +	.probe =	da7210_probe, +	.read		= da7210_read, +	.write		= da7210_write, +	.reg_cache_size	= ARRAY_SIZE(da7210_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default	= da7210_reg, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static int __devinit da7210_i2c_probe(struct i2c_client *i2c,  			   	      const struct i2c_device_id *id)  {  	struct da7210_priv *da7210; -	struct snd_soc_codec *codec;  	int ret;  	da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);  	if (!da7210)  		return -ENOMEM; -	codec = &da7210->codec; -	codec->dev = &i2c->dev; -  	i2c_set_clientdata(i2c, da7210); -	codec->control_data = i2c; +	da7210->control_data = i2c; +	da7210->control_type = SND_SOC_I2C; -	ret = da7210_init(da7210); -	if (ret < 0) { -		pr_err("Failed to initialise da7210 audio codec\n"); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_da7210, &da7210_dai, 1); +	if (ret < 0)  		kfree(da7210); -	}  	return ret;  }  static int __devexit da7210_i2c_remove(struct i2c_client *client)  { -	struct da7210_priv *da7210 = i2c_get_clientdata(client); - -	snd_soc_unregister_dai(&da7210_dai); -	kfree(da7210->codec.reg_cache); -	kfree(da7210); -	da7210_codec = NULL; - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);  /* I2C codec control layer */  static struct i2c_driver da7210_i2c_driver = {  	.driver = { -		.name = "DA7210 I2C Codec", +		.name = "da7210-codec",  		.owner = THIS_MODULE,  	},  	.probe = da7210_i2c_probe, @@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = {  };  #endif -static int da7210_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	if (!da7210_codec) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = da7210_codec; -	codec = da7210_codec; - -	/* Register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; - -	snd_soc_add_controls(da7210_codec, da7210_snd_controls, -			     ARRAY_SIZE(da7210_snd_controls)); - -	dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - -pcm_err: -	return ret; -} - -static int da7210_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_da7210 = { -	.probe =	da7210_probe, -	.remove =	da7210_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_da7210); -  static int __init da7210_modinit(void)  {  	int ret = 0; diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h deleted file mode 100644 index 390d621eb742..000000000000 --- a/sound/soc/codecs/da7210.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * da7210.h  --  audio driver for da7210 - * - * Copyright (c) 2009 Dialog Semiconductor - * Written by David Chen <Dajun.chen@diasemi.com> - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com> - * - * This program is free software; you can redistribute  it and/or modify it - * under  the terms of  the GNU General  Public License as published by the - * Free Software Foundation;  either version 2 of the  License, or (at your - * option) any later version. - * - */ - -#ifndef _DA7210_H -#define _DA7210_H - -extern struct snd_soc_dai da7210_dai; -extern struct snd_soc_codec_device soc_codec_dev_da7210; - -#endif - diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 66557de1e4fe..16253ec9b022 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {  struct jz4740_codec {  	void __iomem *base;  	struct resource *mem; - -	uint32_t reg_cache[2]; -	struct snd_soc_codec codec;  }; -static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec) -{ -	return container_of(codec, struct jz4740_codec, codec); -} -  static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,  	unsigned int reg)  { -	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); +	struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);  	return readl(jz4740_codec->base + (reg << 2));  }  static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,  	unsigned int val)  { -	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); +	struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); +	u32 *cache = codec->reg_cache; -	jz4740_codec->reg_cache[reg] = val; +	cache[reg] = val;  	writel(val, jz4740_codec->base + (reg << 2));  	return 0; @@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,  {  	uint32_t val;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec =rtd->codec;  	switch (params_rate(params)) {  	case 8000: @@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {  	.hw_params = jz4740_codec_hw_params,  }; -struct snd_soc_dai jz4740_codec_dai = { -	.name = "jz4740", +static struct snd_soc_dai_driver jz4740_codec_dai = { +	.name = "jz4740-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {  	.ops = &jz4740_codec_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(jz4740_codec_dai);  static void jz4740_codec_wakeup(struct snd_soc_codec *codec)  { @@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,  	return 0;  } -static struct snd_soc_codec *jz4740_codec_codec; - -static int jz4740_codec_dev_probe(struct platform_device *pdev) +static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)  { -	int ret; -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = jz4740_codec_codec; - -	BUG_ON(!codec); - -	socdev->card->codec = codec; - -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret) { -		dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret); -		return ret; -	} +	snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, +			JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);  	snd_soc_add_controls(codec, jz4740_codec_controls,  		ARRAY_SIZE(jz4740_codec_controls)); @@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev)  	snd_soc_dapm_new_widgets(codec); +	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +  	return 0;  } -static int jz4740_codec_dev_remove(struct platform_device *pdev) +static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  }  #ifdef CONFIG_PM_SLEEP -static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) +static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);  } -static int jz4740_codec_resume(struct platform_device *pdev) +static int jz4740_codec_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  } @@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev)  #define jz4740_codec_resume NULL  #endif -struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { +static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {  	.probe = jz4740_codec_dev_probe,  	.remove = jz4740_codec_dev_remove,  	.suspend = jz4740_codec_suspend,  	.resume = jz4740_codec_resume, +	.read = jz4740_codec_read, +	.write = jz4740_codec_write, +	.set_bias_level = jz4740_codec_set_bias_level, +	.reg_cache_default	= jz4740_codec_regs, +	.reg_word_size = sizeof(u32), +	.reg_cache_size	= 2,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);  static int __devinit jz4740_codec_probe(struct platform_device *pdev)  {  	int ret;  	struct jz4740_codec *jz4740_codec; -	struct snd_soc_codec *codec;  	struct resource *mem;  	jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); @@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)  	}  	jz4740_codec->mem = mem; -	jz4740_codec_dai.dev = &pdev->dev; - -	codec = &jz4740_codec->codec; - -	codec->dev		= &pdev->dev; -	codec->name		= "jz4740"; -	codec->owner		= THIS_MODULE; - -	codec->read		= jz4740_codec_read; -	codec->write		= jz4740_codec_write; -	codec->set_bias_level	= jz4740_codec_set_bias_level; -	codec->bias_level	= SND_SOC_BIAS_OFF; - -	codec->dai		= &jz4740_codec_dai; -	codec->num_dai		= 1; - -	codec->reg_cache	= jz4740_codec->reg_cache; -	codec->reg_cache_size	= 2; -	memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs)); - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	jz4740_codec_codec = codec; - -	snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, -			JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); -  	platform_set_drvdata(pdev, jz4740_codec); -	ret = snd_soc_register_codec(codec); +	ret = snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);  	if (ret) {  		dev_err(&pdev->dev, "Failed to register codec\n");  		goto err_iounmap;  	} -	ret = snd_soc_register_dai(&jz4740_codec_dai); -	if (ret) { -		dev_err(&pdev->dev, "Failed to register codec dai\n"); -		goto err_unregister_codec; -	} - -	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -  	return 0; -err_unregister_codec: -	snd_soc_unregister_codec(codec);  err_iounmap:  	iounmap(jz4740_codec->base);  err_release_mem_region: @@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)  	struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);  	struct resource *mem = jz4740_codec->mem; -	snd_soc_unregister_dai(&jz4740_codec_dai); -	snd_soc_unregister_codec(&jz4740_codec->codec); +	snd_soc_unregister_codec(&pdev->dev);  	iounmap(jz4740_codec->base);  	release_mem_region(mem->start, resource_size(mem)); diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h deleted file mode 100644 index b5a0691be763..000000000000 --- a/sound/soc/codecs/jz4740.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de> - * - * 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. - * - *  You should have received a copy of the  GNU General Public License along - *  with this program; if not, write  to the Free Software Foundation, Inc., - *  675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__ -#define __SND_SOC_CODECS_JZ4740_CODEC_H__ - -extern struct snd_soc_dai jz4740_codec_dai; -extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec; - -#endif diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 5a5f187a2657..bd8f26e41602 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -32,8 +32,8 @@  #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |	\  		       SNDRV_PCM_RATE_48000) -struct snd_soc_dai pcm3008_dai = { -	.name = "PCM3008 HiFi", +static struct snd_soc_dai_driver pcm3008_dai = { +	.name = "pcm3008-hifi",  	.playback = {  		.stream_name = "PCM3008 Playback",  		.channels_min = 1, @@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {  		.formats = SNDRV_PCM_FMTBIT_S16_LE,  	},  }; -EXPORT_SYMBOL_GPL(pcm3008_dai);  static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)  { @@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)  	gpio_free(setup->pdda_pin);  } -static int pcm3008_soc_probe(struct platform_device *pdev) +static int pcm3008_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct pcm3008_setup_data *setup = socdev->codec_data; +	struct pcm3008_setup_data *setup = codec->dev->platform_data;  	int ret = 0;  	printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (!socdev->card->codec) -		return -ENOMEM; - -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->name = "PCM3008"; -	codec->owner = THIS_MODULE; -	codec->dai = &pcm3008_dai; -	codec->num_dai = 1; -	codec->write = NULL; -	codec->read = NULL; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	/* Register PCMs. */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "pcm3008: failed to create pcms\n"); -		goto pcm_err; -	} -  	/* DEM1  DEM0  DE-EMPHASIS_MODE  	 * Low   Low   De-emphasis 44.1 kHz ON  	 * Low   High  De-emphasis OFF @@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)  gpio_err:  	pcm3008_gpio_free(setup); -pcm_err: -	kfree(socdev->card->codec);  	return ret;  } -static int pcm3008_soc_remove(struct platform_device *pdev) +static int pcm3008_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -	struct pcm3008_setup_data *setup = socdev->codec_data; - -	if (!codec) -		return 0; +	struct pcm3008_setup_data *setup = codec->dev->platform_data;  	pcm3008_gpio_free(setup); -	snd_soc_free_pcms(socdev); -	kfree(socdev->card->codec); -  	return 0;  }  #ifdef CONFIG_PM -static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct pcm3008_setup_data *setup = socdev->codec_data; +	struct pcm3008_setup_data *setup = codec->dev->platform_data;  	gpio_set_value(setup->pdad_pin, 0);  	gpio_set_value(setup->pdda_pin, 0); @@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)  	return 0;  } -static int pcm3008_soc_resume(struct platform_device *pdev) +static int pcm3008_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct pcm3008_setup_data *setup = socdev->codec_data; +	struct pcm3008_setup_data *setup = codec->dev->platform_data;  	gpio_set_value(setup->pdad_pin, 1);  	gpio_set_value(setup->pdda_pin, 1); @@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev)  #define pcm3008_soc_resume NULL  #endif -struct snd_soc_codec_device soc_codec_dev_pcm3008 = { +static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {  	.probe = 	pcm3008_soc_probe,  	.remove = 	pcm3008_soc_remove,  	.suspend =	pcm3008_soc_suspend,  	.resume =	pcm3008_soc_resume,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008); -static int __init pcm3008_init(void) +static int __devinit pcm3008_codec_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_pcm3008, &pcm3008_dai, 1); +} + +static int __devexit pcm3008_codec_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +MODULE_ALIAS("platform:pcm3008-codec"); + +static struct platform_driver pcm3008_codec_driver = { +	.probe		= pcm3008_codec_probe, +	.remove		= __devexit_p(pcm3008_codec_remove), +	.driver		= { +		.name	= "pcm3008-codec", +		.owner	= THIS_MODULE, +	}, +}; + +static int __init pcm3008_modinit(void)  { -	return snd_soc_register_dai(&pcm3008_dai); +	return platform_driver_register(&pcm3008_codec_driver);  } -module_init(pcm3008_init); +module_init(pcm3008_modinit);  static void __exit pcm3008_exit(void)  { -	snd_soc_unregister_dai(&pcm3008_dai); +	platform_driver_unregister(&pcm3008_codec_driver);  }  module_exit(pcm3008_exit); diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h index d04e87d3c060..7e5489ab4812 100644 --- a/sound/soc/codecs/pcm3008.h +++ b/sound/soc/codecs/pcm3008.h @@ -19,7 +19,4 @@ struct pcm3008_setup_data {  	unsigned pdda_pin;  }; -extern struct snd_soc_codec_device soc_codec_dev_pcm3008; -extern struct snd_soc_dai pcm3008_dai; -  #endif diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c index 9119836051a4..4c32b54913ad 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transciever.c @@ -21,57 +21,16 @@  #include <sound/pcm.h>  #include <sound/initval.h> -#include "spdif_transciever.h" -  MODULE_LICENSE("GPL");  #define STUB_RATES	SNDRV_PCM_RATE_8000_96000  #define STUB_FORMATS	SNDRV_PCM_FMTBIT_S16_LE -static struct snd_soc_codec *spdif_dit_codec; - -static int spdif_dit_codec_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	if (spdif_dit_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = spdif_dit_codec; -	codec = spdif_dit_codec; - -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto err_create_pcms; -	} - -	return 0; - -err_create_pcms: -	return ret; -} - -static int spdif_dit_codec_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_dev_spdif_dit = { -	.probe		= spdif_dit_codec_probe, -	.remove		= spdif_dit_codec_remove, -}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit); +static struct snd_soc_codec_driver soc_codec_spdif_dit; -struct snd_soc_dai dit_stub_dai = { -	.name		= "DIT", +static struct snd_soc_dai_driver dit_stub_dai = { +	.name		= "dit-hifi",  	.playback 	= {  		.stream_name	= "Playback",  		.channels_min	= 1, @@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = {  		.formats	= STUB_FORMATS,  	},  }; -EXPORT_SYMBOL_GPL(dit_stub_dai);  static int spdif_dit_probe(struct platform_device *pdev)  { -	struct snd_soc_codec *codec; -	int ret; - -	if (spdif_dit_codec) { -		dev_err(&pdev->dev, "Another Codec is registered\n"); -		ret = -EINVAL; -		goto err_reg_codec; -	} - -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; - -	codec->dev = &pdev->dev; - -	mutex_init(&codec->mutex); - -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "spdif-dit"; -	codec->owner = THIS_MODULE; -	codec->dai = &dit_stub_dai; -	codec->num_dai = 1; - -	spdif_dit_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_reg_codec; -	} - -	dit_stub_dai.dev = &pdev->dev; -	ret = snd_soc_register_dai(&dit_stub_dai); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to register dai: %d\n", ret); -		goto err_reg_dai; -	} - -	return 0; - -err_reg_dai: -	snd_soc_unregister_codec(codec); -err_reg_codec: -	kfree(spdif_dit_codec); -	return ret; +	return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit, +			&dit_stub_dai, 1);  }  static int spdif_dit_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&dit_stub_dai); -	snd_soc_unregister_codec(spdif_dit_codec); -	kfree(spdif_dit_codec); -	spdif_dit_codec = NULL; +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  } diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h deleted file mode 100644 index 1e102124f546..000000000000 --- a/sound/soc/codecs/spdif_transciever.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * ALSA SoC DIT/DIR driver header - * - * Author:      Steve Chen,  <schen@mvista.com> - * Copyright:   (C) 2008 MontaVista Software, Inc., <source@mvista.com> - * - * 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 CODEC_STUBS_H -#define CODEC_STUBS_H - -extern struct snd_soc_codec_device soc_codec_dev_spdif_dit; -extern struct snd_soc_dai dit_stub_dai; - -#endif /* CODEC_STUBS_H */ diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index b47ed4f6ab20..67d8c044ca04 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -45,11 +45,11 @@  #define SSM2602_VERSION "0.1" -struct snd_soc_codec_device soc_codec_dev_ssm2602; -  /* codec private data */  struct ssm2602_priv {  	unsigned int sysclk; +	enum snd_soc_control_type control_type; +	void *control_data;  	struct snd_pcm_substream *master_substream;  	struct snd_pcm_substream *slave_substream;  }; @@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,  {  	u16 srate;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);  	struct i2c_client *i2c = codec->control_data;  	u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; @@ -321,8 +320,7 @@ static int ssm2602_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);  	struct i2c_client *i2c = codec->control_data;  	struct snd_pcm_runtime *master_runtime; @@ -360,8 +358,7 @@ static int ssm2602_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; +	struct snd_soc_codec *codec = rtd->codec;  	/* set active */  	ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); @@ -372,8 +369,7 @@ static void ssm2602_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);  	/* deactivate */ @@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = {  	.set_fmt	= ssm2602_set_dai_fmt,  }; -struct snd_soc_dai ssm2602_dai = { -	.name = "SSM2602", +static struct snd_soc_dai_driver ssm2602_dai = { +	.name = "ssm2602-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = {  		.formats = SSM2602_FORMATS,},  	.ops = &ssm2602_dai_ops,  }; -EXPORT_SYMBOL_GPL(ssm2602_dai); -static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) +static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int ssm2602_resume(struct platform_device *pdev) +static int ssm2602_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -563,36 +553,18 @@ static int ssm2602_resume(struct platform_device *pdev)  	return 0;  } -/* - * initialise the ssm2602 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ssm2602_init(struct snd_soc_device *socdev) +static int ssm2602_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int reg, ret = 0; - -	codec->name = "SSM2602"; -	codec->owner = THIS_MODULE; -	codec->read = ssm2602_read_reg_cache; -	codec->write = ssm2602_write; -	codec->set_bias_level = ssm2602_set_bias_level; -	codec->dai = &ssm2602_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = sizeof(ssm2602_reg); -	codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg), -					GFP_KERNEL); -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); +	int ret = 0, reg; + +	pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); + +	codec->bias_level = SND_SOC_BIAS_OFF, +	codec->control_data = ssm2602->control_data;  	ssm2602_reset(codec); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		pr_err("ssm2602: failed to create pcms\n"); -		goto pcm_err; -	}  	/*power on device*/  	ssm2602_write(codec, SSM2602_ACTIVE, 0);  	/* set the update bits */ @@ -614,13 +586,27 @@ static int ssm2602_init(struct snd_soc_device *socdev)  	ssm2602_add_widgets(codec);  	return ret; +} -pcm_err: -	kfree(codec->reg_cache); -	return ret; +/* remove everything here */ +static int ssm2602_remove(struct snd_soc_codec *codec) +{ +	ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -static struct snd_soc_device *ssm2602_socdev; +static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { +	.probe =	ssm2602_probe, +	.remove =	ssm2602_remove, +	.suspend =	ssm2602_suspend, +	.resume =	ssm2602_resume, +	.read = ssm2602_read_reg_cache, +	.write = ssm2602_write, +	.set_bias_level = ssm2602_set_bias_level, +	.reg_cache_size = sizeof(ssm2602_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = ssm2602_reg, +};  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  /* @@ -632,24 +618,28 @@ static struct snd_soc_device *ssm2602_socdev;  static int ssm2602_i2c_probe(struct i2c_client *i2c,  			     const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = ssm2602_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct ssm2602_priv *ssm2602;  	int ret; -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; +	ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); +	if (ssm2602 == NULL) +		return -ENOMEM; -	ret = ssm2602_init(socdev); -	if (ret < 0) -		pr_err("failed to initialise SSM2602\n"); +	i2c_set_clientdata(i2c, ssm2602); +	ssm2602->control_data = i2c; +	ssm2602->control_type = SND_SOC_I2C; +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_ssm2602, &ssm2602_dai, 1); +	if (ret < 0) +		kfree(ssm2602);  	return ret;  }  static int ssm2602_i2c_remove(struct i2c_client *client)  { -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -658,130 +648,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {  	{ }  };  MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); +  /* corgi i2c codec control layer */  static struct i2c_driver ssm2602_i2c_driver = {  	.driver = { -		.name = "SSM2602 I2C Codec", +		.name = "ssm2602-codec",  		.owner = THIS_MODULE,  	},  	.probe = ssm2602_i2c_probe,  	.remove = ssm2602_i2c_remove,  	.id_table = ssm2602_i2c_id,  }; - -static int ssm2602_add_i2c_device(struct platform_device *pdev, -				  const struct ssm2602_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&ssm2602_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "ssm2602", I2C_NAME_SIZE); -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -		setup->i2c_bus); -		goto err_driver; -	} -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -		(unsigned int)info.addr); -		goto err_driver; -	} -	return 0; -err_driver: -	i2c_del_driver(&ssm2602_i2c_driver); -	return -ENODEV; -}  #endif -static int ssm2602_probe(struct platform_device *pdev) + +static int __init ssm2602_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct ssm2602_setup_data *setup; -	struct snd_soc_codec *codec; -	struct ssm2602_priv *ssm2602;  	int ret = 0; - -	pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); - -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; - -	ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); -	if (ssm2602 == NULL) { -		kfree(codec); -		return -ENOMEM; -	} - -	snd_soc_codec_set_drvdata(codec, ssm2602); -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	ssm2602_socdev = socdev;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		codec->hw_write = (hw_write_t)i2c_master_send; -		ret = ssm2602_add_i2c_device(pdev, setup); +	ret = i2c_add_driver(&ssm2602_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", +		       ret);  	} -#else -	/* other interfaces */  #endif  	return ret;  } +module_init(ssm2602_modinit); -/* remove everything here */ -static int ssm2602_remove(struct platform_device *pdev) +static void __exit ssm2602_exit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev);  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	i2c_unregister_device(codec->control_data);  	i2c_del_driver(&ssm2602_i2c_driver);  #endif -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ssm2602 = { -	.probe = 	ssm2602_probe, -	.remove = 	ssm2602_remove, -	.suspend = 	ssm2602_suspend, -	.resume =	ssm2602_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); - -static int __init ssm2602_modinit(void) -{ -	return snd_soc_register_dai(&ssm2602_dai); -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ -	snd_soc_unregister_dai(&ssm2602_dai);  }  module_exit(ssm2602_exit); diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index f344e6d76e31..42a47d0f8e25 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -124,7 +124,4 @@ struct ssm2602_setup_data {  	unsigned short i2c_address;  }; -extern struct snd_soc_dai ssm2602_dai; -extern struct snd_soc_codec_device soc_codec_dev_ssm2602; -  #endif diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ee86568545c2..00d67cc8e206 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -25,7 +25,6 @@  #include <sound/pcm_params.h>  #include <sound/soc.h>  #include <sound/tlv.h> -#include <sound/soc-of-simple.h>  #include "stac9766.h" @@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)  	return 0;  } -static int stac9766_codec_suspend(struct platform_device *pdev, +static int stac9766_codec_suspend(struct snd_soc_codec *codec,  				  pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int stac9766_codec_resume(struct platform_device *pdev) +static int stac9766_codec_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	u16 id, reset;  	reset = 0; @@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = {  	.prepare = ac97_digital_prepare,  }; -struct snd_soc_dai stac9766_dai[] = { +static struct snd_soc_dai_driver stac9766_dai[] = {  { -	.name = "stac9766 analog", -	.id = 0, +	.name = "stac9766-hifi-analog",  	.ac97_control = 1,  	/* stream cababilities */ @@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = {  	.ops = &stac9766_dai_ops_analog,  },  { -	.name = "stac9766 IEC958", -	.id = 1, +	.name = "stac9766-hifi-IEC958",  	.ac97_control = 1,  	/* stream cababilities */ @@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = {  	.ops = &stac9766_dai_ops_digital,  }  }; -EXPORT_SYMBOL_GPL(stac9766_dai); -static int stac9766_codec_probe(struct platform_device *pdev) +static int stac9766_codec_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec;  	int ret = 0;  	printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (socdev->card->codec == NULL) -		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg), -				   GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} -	codec->reg_cache_size = sizeof(stac9766_reg); -	codec->reg_cache_step = 2; - -	codec->name = "STAC9766"; -	codec->owner = THIS_MODULE; -	codec->dai = stac9766_dai; -	codec->num_dai = ARRAY_SIZE(stac9766_dai); -	codec->write = stac9766_ac97_write; -	codec->read = stac9766_ac97_read; -	codec->set_bias_level = stac9766_set_bias_level; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0)  		goto codec_err; -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; -  	/* do a cold reset for the controller and then try  	 * a warm reset followed by an optional cold reset for codec */  	stac9766_reset(codec, 0);  	ret = stac9766_reset(codec, 1);  	if (ret < 0) {  		printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); -		goto reset_err; +		goto codec_err;  	}  	stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev)  	return 0; -reset_err: -	snd_soc_free_pcms(socdev); -pcm_err: -	snd_soc_free_ac97_codec(codec);  codec_err: -	kfree(snd_soc_codec_get_drvdata(codec)); -cache_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL; +	snd_soc_free_ac97_codec(codec);  	return ret;  } -static int stac9766_codec_remove(struct platform_device *pdev) +static int stac9766_codec_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; - -	snd_soc_free_pcms(socdev);  	snd_soc_free_ac97_codec(codec); -	kfree(codec->reg_cache); -	kfree(codec);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_stac9766 = { +static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { +	.write = stac9766_ac97_write, +	.read = stac9766_ac97_read, +	.set_bias_level = stac9766_set_bias_level,  	.probe = stac9766_codec_probe,  	.remove = stac9766_codec_remove,  	.suspend = stac9766_codec_suspend,  	.resume = stac9766_codec_resume, +	.reg_cache_size = sizeof(stac9766_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_step = 2, +}; + +static __devinit int stac9766_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai)); +} + +static int __devexit stac9766_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver stac9766_codec_driver = { +	.driver = { +			.name = "stac9766-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = stac9766_probe, +	.remove = __devexit_p(stac9766_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); + +static int __init stac9766_init(void) +{ +	return platform_driver_register(&stac9766_codec_driver); +} +module_init(stac9766_init); + +static void __exit stac9766_exit(void) +{ +	platform_driver_unregister(&stac9766_codec_driver); +} +module_exit(stac9766_exit);  MODULE_DESCRIPTION("ASoC stac9766 driver");  MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h index 65642eb8393e..c726f907e2c0 100644 --- a/sound/soc/codecs/stac9766.h +++ b/sound/soc/codecs/stac9766.h @@ -14,8 +14,4 @@  #define STAC9766_DAI_AC97_ANALOG		0  #define STAC9766_DAI_AC97_DIGITAL		1 -extern struct snd_soc_dai stac9766_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_stac9766; - -  #endif diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 0a4b0fef3355..e8652b1ae326 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = {  /* AIC23 driver data */  struct aic23 { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	int mclk;  	int requested_adc;  	int requested_dac; @@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 iface_reg;  	int ret; -	struct aic23 *aic23 = container_of(codec, struct aic23, codec); +	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);  	u32 sample_rate_adc = aic23->requested_adc;  	u32 sample_rate_dac = aic23->requested_dac;  	u32 sample_rate = params_rate(params); @@ -452,8 +452,7 @@ static int tlv320aic23_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; +	struct snd_soc_codec *codec = rtd->codec;  	/* set active */  	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); @@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(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; -	struct aic23 *aic23 = container_of(codec, struct aic23, codec); +	struct snd_soc_codec *codec = rtd->codec; +	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);  	/* deactivate */  	if (!codec->active) { @@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,  static int tlv320aic23_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 aic23 *aic23 = container_of(codec, struct aic23, codec); +	struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);  	aic23->mclk = freq;  	return 0;  } @@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {  	.set_sysclk	= tlv320aic23_set_dai_sysclk,  }; -struct snd_soc_dai tlv320aic23_dai = { -	.name = "tlv320aic23", +static struct snd_soc_dai_driver tlv320aic23_dai = { +	.name = "tlv320aic23-hifi",  	.playback = {  		     .stream_name = "Playback",  		     .channels_min = 2, @@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = {  		    .formats = AIC23_FORMATS,},  	.ops = &tlv320aic23_dai_ops,  }; -EXPORT_SYMBOL_GPL(tlv320aic23_dai); -static int tlv320aic23_suspend(struct platform_device *pdev, +static int tlv320aic23_suspend(struct snd_soc_codec *codec,  			       pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int tlv320aic23_resume(struct platform_device *pdev) +static int tlv320aic23_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	u16 reg;  	/* Sync reg_cache with the hardware */ @@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)  	return 0;  } -/* - * initialise the AIC23 driver - * register the mixer and dsp interfaces with the kernel - */ -static int tlv320aic23_init(struct snd_soc_device *socdev) +static int tlv320aic23_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret = 0; -	u16 reg; +	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); +	int reg; -	codec->name = "tlv320aic23"; -	codec->owner = THIS_MODULE; -	codec->read = tlv320aic23_read_reg_cache; -	codec->write = tlv320aic23_write; -	codec->set_bias_level = tlv320aic23_set_bias_level; -	codec->dai = &tlv320aic23_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg); -	codec->reg_cache = -	    kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL); -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); +	codec->control_data = aic23->control_data; +	codec->hw_write = (hw_write_t)i2c_master_send; +	codec->hw_read = NULL;  	/* Reset codec */  	tlv320aic23_write(codec, TLV320AIC23_RESET, 0); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "tlv320aic23: failed to create pcms\n"); -		goto pcm_err; -	} -  	/* power on device */  	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)  				ARRAY_SIZE(tlv320aic23_snd_controls));  	tlv320aic23_add_widgets(codec); -	return ret; +	return 0; +} -pcm_err: -	kfree(codec->reg_cache); -	return ret; +static int tlv320aic23_remove(struct snd_soc_codec *codec) +{ +	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -static struct snd_soc_device *tlv320aic23_socdev; + +static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { +	.reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = tlv320aic23_reg, +	.probe = tlv320aic23_probe, +	.remove = tlv320aic23_remove, +	.suspend = tlv320aic23_suspend, +	.resume = tlv320aic23_resume, +	.read = tlv320aic23_read_reg_cache, +	.write = tlv320aic23_write, +	.set_bias_level = tlv320aic23_set_bias_level, +};  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  /* @@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev;  static int tlv320aic23_codec_probe(struct i2c_client *i2c,  				   const struct i2c_device_id *i2c_id)  { -	struct snd_soc_device *socdev = tlv320aic23_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct aic23 *aic23;  	int ret;  	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))  		return -EINVAL; -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; +	aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); +	if (aic23 == NULL) +		return -ENOMEM; -	ret = tlv320aic23_init(socdev); -	if (ret < 0) { -		printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); -		goto err; -	} -	return ret; +	i2c_set_clientdata(i2c, aic23); +	aic23->control_data = i2c; +	aic23->control_type = SND_SOC_I2C; -err: -	kfree(codec); -	kfree(i2c); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); +	if (ret < 0) +		kfree(aic23);  	return ret;  }  static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)  { -	put_device(&i2c->dev); +	snd_soc_unregister_codec(&i2c->dev); +	kfree(i2c_get_clientdata(i2c));  	return 0;  } @@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);  static struct i2c_driver tlv320aic23_i2c_driver = {  	.driver = { -		   .name = "tlv320aic23", +		   .name = "tlv320aic23-codec",  		   },  	.probe = tlv320aic23_codec_probe,  	.remove = __exit_p(tlv320aic23_i2c_remove), @@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {  #endif -static int tlv320aic23_probe(struct platform_device *pdev) +static int __init tlv320aic23_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct aic23 *aic23; -	int ret = 0; - -	printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); - -	aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); -	if (aic23 == NULL) -		return -ENOMEM; -	codec = &aic23->codec; -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	tlv320aic23_socdev = socdev; +	int ret;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	codec->hw_write = (hw_write_t) i2c_master_send; -	codec->hw_read = NULL;  	ret = i2c_add_driver(&tlv320aic23_i2c_driver); -	if (ret != 0) -		printk(KERN_ERR "can't add i2c driver"); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", +		       ret); +	}  #endif  	return ret;  } +module_init(tlv320aic23_modinit); -static int tlv320aic23_remove(struct platform_device *pdev) +static void __exit tlv320aic23_exit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -	struct aic23 *aic23 = container_of(codec, struct aic23, codec); - -	if (codec->control_data) -		tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev);  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&tlv320aic23_i2c_driver);  #endif -	kfree(codec->reg_cache); -	kfree(aic23); - -	return 0; -} -struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = { -	.probe = tlv320aic23_probe, -	.remove = tlv320aic23_remove, -	.suspend = tlv320aic23_suspend, -	.resume = tlv320aic23_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); - -static int __init tlv320aic23_modinit(void) -{ -	return snd_soc_register_dai(&tlv320aic23_dai); -} -module_init(tlv320aic23_modinit); - -static void __exit tlv320aic23_exit(void) -{ -	snd_soc_unregister_dai(&tlv320aic23_dai);  }  module_exit(tlv320aic23_exit); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index 79d1faf8e570..e804120bd3da 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -116,7 +116,4 @@  #define TLV320AIC23_SIDETONE_12		0x080  #define TLV320AIC23_SIDETONE_18		0x0c0 -extern struct snd_soc_dai tlv320aic23_dai; -extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23; -  #endif /* _TLV320AIC23_H */ diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index f0e00fd4b435..6b7d71ec0004 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -19,7 +19,6 @@  #include <sound/pcm_params.h>  #include <sound/soc.h>  #include <sound/soc-dapm.h> -#include <sound/soc-of-simple.h>  #include <sound/initval.h>  #include "tlv320aic26.h" @@ -130,8 +129,7 @@ static int aic26_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);  	int fsref, divisor, wlen, pval, jval, dval, qval;  	u16 reg; @@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = {  	.set_fmt	= aic26_set_fmt,  }; -struct snd_soc_dai aic26_dai = { -	.name = "tlv320aic26", +static struct snd_soc_dai_driver aic26_dai = { +	.name = "tlv320aic26-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = {  	},  	.ops = &aic26_dai_ops,  }; -EXPORT_SYMBOL_GPL(aic26_dai);  /* ---------------------------------------------------------------------   * ALSA controls @@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = {  };  /* --------------------------------------------------------------------- - * SoC CODEC portion of driver: probe and release routines - */ -static int aic26_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct aic26 *aic26; -	int ret, err; - -	dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); -	dev_dbg(&pdev->dev, "socdev=%p\n", socdev); -	dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); - -	/* Fetch the relevant aic26 private data here (it's already been -	 * stored in the .codec pointer) */ -	aic26 = socdev->codec_data; -	if (aic26 == NULL) { -		dev_err(&pdev->dev, "aic26: missing codec pointer\n"); -		return -ENODEV; -	} -	codec = &aic26->codec; -	socdev->card->codec = codec; - -	dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", -		&pdev->dev, socdev->dev); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(&pdev->dev, "aic26: failed to create pcms\n"); -		return -ENODEV; -	} - -	/* register controls */ -	dev_dbg(&pdev->dev, "Registering controls\n"); -	err = snd_soc_add_controls(codec, aic26_snd_controls, -			ARRAY_SIZE(aic26_snd_controls)); -	WARN_ON(err < 0); - -	return 0; -} - -static int aic26_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 aic26_soc_codec_dev = { -	.probe = aic26_probe, -	.remove = aic26_remove, -}; -EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); - -/* ---------------------------------------------------------------------   * SPI device portion of driver: sysfs files for debugging   */ @@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev,  static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);  /* --------------------------------------------------------------------- - * SPI device portion of driver: probe and release routines and SPI - * 				 driver registration. + * SoC CODEC portion of driver: probe and release routines   */ -static int aic26_spi_probe(struct spi_device *spi) +static int aic26_probe(struct snd_soc_codec *codec)  { -	struct aic26 *aic26; -	int ret, i, reg; - -	dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); - -	/* Allocate driver data */ -	aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); -	if (!aic26) -		return -ENOMEM; - -	/* Initialize the driver data */ -	aic26->spi = spi; -	dev_set_drvdata(&spi->dev, aic26); +	struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); +	int ret, err, i, reg; -	/* Setup what we can in the codec structure so that the register -	 * access functions will work as expected.  More will be filled -	 * out when it is probed by the SoC CODEC part of this driver */ -	snd_soc_codec_set_drvdata(&aic26->codec, aic26); -	aic26->codec.name = "aic26"; -	aic26->codec.owner = THIS_MODULE; -	aic26->codec.dai = &aic26_dai; -	aic26->codec.num_dai = 1; -	aic26->codec.read = aic26_reg_read; -	aic26->codec.write = aic26_reg_write; -	aic26->master = 1; -	mutex_init(&aic26->codec.mutex); -	INIT_LIST_HEAD(&aic26->codec.dapm_widgets); -	INIT_LIST_HEAD(&aic26->codec.dapm_paths); -	aic26->codec.reg_cache_size = AIC26_NUM_REGS; -	aic26->codec.reg_cache = aic26->reg_cache; - -	aic26_dai.dev = &spi->dev; -	ret = snd_soc_register_dai(&aic26_dai); -	if (ret != 0) { -		dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); -		kfree(aic26); -		return ret; -	} +	dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");  	/* Reset the codec to power on defaults */ -	aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); +	aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00);  	/* Power up CODEC */ -	aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); +	aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);  	/* Audio Control 3 (master mode, fsref rate) */ -	reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); +	reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3);  	reg &= ~0xf800;  	reg |= 0x0800; /* set master mode */ -	aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); +	aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);  	/* Fill register cache */  	for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) -		aic26_reg_read(&aic26->codec, i); +		aic26_reg_read(codec, i);  	/* Register the sysfs files for debugging */  	/* Create SysFS files */ -	ret = device_create_file(&spi->dev, &dev_attr_keyclick); +	ret = device_create_file(codec->dev, &dev_attr_keyclick);  	if (ret) -		dev_info(&spi->dev, "error creating sysfs files\n"); +		dev_info(codec->dev, "error creating sysfs files\n"); -#if defined(CONFIG_SND_SOC_OF_SIMPLE) -	/* Tell the of_soc helper about this codec */ -	of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, -				  spi->dev.archdata.of_node); -#endif +	/* register controls */ +	dev_dbg(codec->dev, "Registering controls\n"); +	err = snd_soc_add_controls(codec, aic26_snd_controls, +			ARRAY_SIZE(aic26_snd_controls)); +	WARN_ON(err < 0); -	dev_dbg(&spi->dev, "SPI device initialized\n");  	return 0;  } -static int aic26_spi_remove(struct spi_device *spi) +static struct snd_soc_codec_driver aic26_soc_codec_dev = { +	.probe = aic26_probe, +	.read = aic26_reg_read, +	.write = aic26_reg_write, +	.reg_cache_size = AIC26_NUM_REGS, +	.reg_word_size = sizeof(u16), +}; + +/* --------------------------------------------------------------------- + * SPI device portion of driver: probe and release routines and SPI + * 				 driver registration. + */ +static int aic26_spi_probe(struct spi_device *spi)  { -	struct aic26 *aic26 = dev_get_drvdata(&spi->dev); +	struct aic26 *aic26; +	int ret; -	snd_soc_unregister_dai(&aic26_dai); -	kfree(aic26); +	dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); + +	/* Allocate driver data */ +	aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); +	if (!aic26) +		return -ENOMEM; +	/* Initialize the driver data */ +	aic26->spi = spi; +	dev_set_drvdata(&spi->dev, aic26); +	aic26->master = 1; + +	ret = snd_soc_register_codec(&spi->dev, +			&aic26_soc_codec_dev, &aic26_dai, 1); +	if (ret < 0) +		kfree(aic26); +	return ret; + +	dev_dbg(&spi->dev, "SPI device initialized\n"); +	return 0; +} + +static int aic26_spi_remove(struct spi_device *spi) +{ +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver aic26_spi = {  	.driver = { -		.name = "tlv320aic26", +		.name = "tlv320aic26-codec",  		.owner = THIS_MODULE,  	},  	.probe = aic26_spi_probe, diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 786ba16c945f..62b1f2261429 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h @@ -90,7 +90,4 @@ enum aic26_wlen {  	AIC26_WLEN_32	= 3 << 10,  }; -extern struct snd_soc_dai aic26_dai; -extern struct snd_soc_codec_device aic26_soc_codec_dev; -  #endif /* _TLV320AIC16_H_ */ diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 71a69908ccf6..43fd9c171742 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -63,8 +63,10 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {  /* codec private data */  struct aic3x_priv { -	struct snd_soc_codec codec;  	struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; +	enum snd_soc_control_type control_type; +	struct aic3x_setup_data *setup; +	void *control_data;  	unsigned int sysclk;  	int master;  	int gpio_reset; @@ -773,8 +775,7 @@ static int aic3x_hw_params(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; +	struct snd_soc_codec *codec =rtd->codec;  	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);  	int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;  	u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; @@ -1101,8 +1102,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = {  	.set_fmt	= aic3x_set_dai_fmt,  }; -struct snd_soc_dai aic3x_dai = { -	.name = "tlv320aic3x", +static struct snd_soc_dai_driver aic3x_dai = { +	.name = "tlv320aic3x-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -1117,22 +1118,16 @@ struct snd_soc_dai aic3x_dai = {  		.formats = AIC3X_FORMATS,},  	.ops = &aic3x_dai_ops,  }; -EXPORT_SYMBOL_GPL(aic3x_dai); -static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) +static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int aic3x_resume(struct platform_device *pdev) +static int aic3x_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u8 *cache = codec->reg_cache; @@ -1157,22 +1152,6 @@ static int aic3x_init(struct snd_soc_codec *codec)  {  	int reg; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "tlv320aic3x"; -	codec->owner = THIS_MODULE; -	codec->read = aic3x_read_reg_cache; -	codec->write = aic3x_write; -	codec->set_bias_level = aic3x_set_bias_level; -	codec->dai = &aic3x_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(aic3x_reg); -	codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL); -	if (codec->reg_cache == NULL) -		return -ENOMEM; -  	aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);  	aic3x_write(codec, AIC3X_RESET, SOFT_RESET); @@ -1245,56 +1224,50 @@ static int aic3x_init(struct snd_soc_codec *codec)  	return 0;  } -static struct snd_soc_codec *aic3x_codec; - -static int aic3x_register(struct snd_soc_codec *codec) +static int aic3x_probe(struct snd_soc_codec *codec)  { -	int ret; +	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); + +	codec->hw_write = (hw_write_t) i2c_master_send; +	codec->control_data = aic3x->control_data; -	ret = aic3x_init(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to initialise device\n"); -		return ret; +	if (aic3x->setup) { +		/* setup GPIO functions */ +		aic3x_write(codec, AIC3X_GPIO1_REG, +			    (aic3x->setup->gpio_func[0] & 0xf) << 4); +		aic3x_write(codec, AIC3X_GPIO2_REG, +			    (aic3x->setup->gpio_func[1] & 0xf) << 4);  	} -	aic3x_codec = codec; +	aic3x_init(codec); -	ret = snd_soc_register_codec(codec); -	if (ret) { -		dev_err(codec->dev, "Failed to register codec\n"); -		return ret; -	} +	snd_soc_add_controls(codec, aic3x_snd_controls, +			     ARRAY_SIZE(aic3x_snd_controls)); -	ret = snd_soc_register_dai(&aic3x_dai); -	if (ret) { -		dev_err(codec->dev, "Failed to register dai\n"); -		snd_soc_unregister_codec(codec); -		return ret; -	} +	aic3x_add_widgets(codec);  	return 0;  } -static int aic3x_unregister(struct aic3x_priv *aic3x) +static int aic3x_remove(struct snd_soc_codec *codec)  { -	aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); - -	snd_soc_unregister_dai(&aic3x_dai); -	snd_soc_unregister_codec(&aic3x->codec); - -	if (aic3x->gpio_reset >= 0) { -		gpio_set_value(aic3x->gpio_reset, 0); -		gpio_free(aic3x->gpio_reset); -	} -	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); -	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); - -	kfree(aic3x); -	aic3x_codec = NULL; - +	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_aic3x = { +	.read = aic3x_read_reg_cache, +	.write = aic3x_write, +	.set_bias_level = aic3x_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(aic3x_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default = aic3x_reg, +	.probe = aic3x_probe, +	.remove = aic3x_remove, +	.suspend = aic3x_suspend, +	.resume = aic3x_resume, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  /*   * AIC3X 2 wire address can be up to 4 devices with device addresses @@ -1308,9 +1281,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)  static int aic3x_i2c_probe(struct i2c_client *i2c,  			   const struct i2c_device_id *id)  { -	struct snd_soc_codec *codec; -	struct aic3x_priv *aic3x;  	struct aic3x_pdata *pdata = i2c->dev.platform_data; +	struct aic3x_setup_data *setup = pdata->setup; +	struct aic3x_priv *aic3x;  	int ret, i;  	aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); @@ -1319,12 +1292,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,  		return -ENOMEM;  	} -	codec = &aic3x->codec; -	codec->dev = &i2c->dev; -	snd_soc_codec_set_drvdata(codec, aic3x); -	codec->control_data = i2c; -	codec->hw_write = (hw_write_t) i2c_master_send; - +	aic3x->control_data = i2c; +	aic3x->setup = setup;  	i2c_set_clientdata(i2c, aic3x);  	aic3x->gpio_reset = -1; @@ -1339,17 +1308,17 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,  	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)  		aic3x->supplies[i].supply = aic3x_supply_names[i]; -	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), +	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies),  				 aic3x->supplies);  	if (ret != 0) { -		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); +		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);  		goto err_get;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),  				    aic3x->supplies);  	if (ret != 0) { -		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); +		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);  		goto err_enable;  	} @@ -1358,7 +1327,11 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,  		gpio_set_value(aic3x->gpio_reset, 1);  	} -	return aic3x_register(codec); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_aic3x, &aic3x_dai, 1); +	if (ret < 0) +		goto err_enable; +	return ret;  err_enable:  	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); @@ -1374,7 +1347,16 @@ static int aic3x_i2c_remove(struct i2c_client *client)  {  	struct aic3x_priv *aic3x = i2c_get_clientdata(client); -	return aic3x_unregister(aic3x); +	if (aic3x->gpio_reset >= 0) { +		gpio_set_value(aic3x->gpio_reset, 0); +		gpio_free(aic3x->gpio_reset); +	} +	regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); +	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); + +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client)); +	return 0;  }  static const struct i2c_device_id aic3x_i2c_id[] = { @@ -1387,7 +1369,7 @@ MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);  /* machine i2c codec control layer */  static struct i2c_driver aic3x_i2c_driver = {  	.driver = { -		.name = "aic3x I2C Codec", +		.name = "tlv320aic3x-codec",  		.owner = THIS_MODULE,  	},  	.probe	= aic3x_i2c_probe, @@ -1409,90 +1391,27 @@ static inline void aic3x_i2c_exit(void)  {  	i2c_del_driver(&aic3x_i2c_driver);  } -#else -static inline void aic3x_i2c_init(void) { } -static inline void aic3x_i2c_exit(void) { }  #endif -static int aic3x_probe(struct platform_device *pdev) +static int __init aic3x_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct aic3x_setup_data *setup; -	struct snd_soc_codec *codec;  	int ret = 0; - -	codec = aic3x_codec; -	if (!codec) { -		dev_err(&pdev->dev, "Codec not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = codec; -	setup = socdev->codec_data; - -	if (setup) { -		/* setup GPIO functions */ -		aic3x_write(codec, AIC3X_GPIO1_REG, -			    (setup->gpio_func[0] & 0xf) << 4); -		aic3x_write(codec, AIC3X_GPIO2_REG, -			    (setup->gpio_func[1] & 0xf) << 4); -	} - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "aic3x: failed to create pcms\n"); -		goto pcm_err; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&aic3x_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", +		       ret);  	} - -	snd_soc_add_controls(codec, aic3x_snd_controls, -			     ARRAY_SIZE(aic3x_snd_controls)); - -	aic3x_add_widgets(codec); - -	return ret; - -pcm_err: -	kfree(codec->reg_cache); +#endif  	return ret;  } - -static int aic3x_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	/* power down chip */ -	if (codec->control_data) -		aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - -	kfree(codec->reg_cache); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_aic3x = { -	.probe = aic3x_probe, -	.remove = aic3x_remove, -	.suspend = aic3x_suspend, -	.resume = aic3x_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); - -static int __init aic3x_modinit(void) -{ -	aic3x_i2c_init(); - -	return 0; -}  module_init(aic3x_modinit);  static void __exit aic3x_exit(void)  { -	aic3x_i2c_exit(); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	i2c_del_driver(&aic3x_i2c_driver); +#endif  }  module_exit(aic3x_exit); diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 9af1c886213c..f6e3d9b42daf 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -199,42 +199,6 @@  /* Default input volume */  #define DEFAULT_GAIN    0x20 -/* GPIO API */ -enum { -	AIC3X_GPIO1_FUNC_DISABLED		= 0, -	AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC	= 1, -	AIC3X_GPIO1_FUNC_CLOCK_MUX		= 2, -	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2		= 3, -	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4		= 4, -	AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8		= 5, -	AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ	= 6, -	AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ		= 7, -	AIC3X_GPIO1_FUNC_INPUT			= 8, -	AIC3X_GPIO1_FUNC_OUTPUT			= 9, -	AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK	= 10, -	AIC3X_GPIO1_FUNC_AUDIO_WORDCLK		= 11, -	AIC3X_GPIO1_FUNC_BUTTON_IRQ		= 12, -	AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ	= 13, -	AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ	= 14, -	AIC3X_GPIO1_FUNC_ALL_IRQ		= 16 -}; - -enum { -	AIC3X_GPIO2_FUNC_DISABLED		= 0, -	AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ	= 2, -	AIC3X_GPIO2_FUNC_INPUT			= 3, -	AIC3X_GPIO2_FUNC_OUTPUT			= 4, -	AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT	= 5, -	AIC3X_GPIO2_FUNC_AUDIO_BITCLK		= 8, -	AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, -	AIC3X_GPIO2_FUNC_ALL_IRQ		= 10, -	AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, -	AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, -	AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ	= 13, -	AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ		= 14, -	AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ	= 15 -}; -  void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);  int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); @@ -281,11 +245,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,  int aic3x_headset_detected(struct snd_soc_codec *codec);  int aic3x_button_pressed(struct snd_soc_codec *codec); -struct aic3x_setup_data { -	unsigned int gpio_func[2]; -}; - -extern struct snd_soc_dai aic3x_dai; -extern struct snd_soc_codec_device soc_codec_dev_aic3x; -  #endif /* _AIC3X_H */ diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 8651b01ed223..a3c5b521da6a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -66,8 +66,6 @@  static void dac33_calculate_times(struct snd_pcm_substream *substream);  static int dac33_prepare_chip(struct snd_pcm_substream *substream); -static struct snd_soc_codec *tlv320dac33_codec; -  enum dac33_state {  	DAC33_IDLE = 0,  	DAC33_PREFILL, @@ -93,7 +91,7 @@ struct tlv320dac33_priv {  	struct mutex mutex;  	struct workqueue_struct *dac33_wq;  	struct work_struct work; -	struct snd_soc_codec codec; +	struct snd_soc_codec *codec;  	struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];  	struct snd_pcm_substream *substream;  	int power_gpio; @@ -128,6 +126,8 @@ struct tlv320dac33_priv {  	unsigned int uthr;  	enum dac33_state state; +	enum snd_soc_control_type control_type; +	void *control_data;  };  static const u8 dac33_reg[DAC33_CACHEREGNUM] = { @@ -650,9 +650,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,  static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)  { -	struct snd_soc_codec *codec; - -	codec = &dac33->codec; +	struct snd_soc_codec *codec = dac33->codec;  	switch (dac33->fifo_mode) {  	case DAC33_FIFO_MODE1: @@ -695,9 +693,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)  static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33)  { -	struct snd_soc_codec *codec; - -	codec = &dac33->codec; +	struct snd_soc_codec *codec = dac33->codec;  	switch (dac33->fifo_mode) {  	case DAC33_FIFO_MODE1: @@ -726,7 +722,7 @@ static void dac33_work(struct work_struct *work)  	u8 reg;  	dac33 = container_of(work, struct tlv320dac33_priv, work); -	codec = &dac33->codec; +	codec = dac33->codec;  	mutex_lock(&dac33->mutex);  	switch (dac33->state) { @@ -787,8 +783,7 @@ static int dac33_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	/* Stream started, save the substream pointer */ @@ -801,8 +796,7 @@ static void dac33_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	dac33->substream = NULL; @@ -817,8 +811,7 @@ static int dac33_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	/* Check parameters for validity */  	switch (params_rate(params)) { @@ -856,8 +849,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,  static int dac33_prepare_chip(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;  	u8 aictrl_a, aictrl_b, fifoctrl_a; @@ -1049,8 +1041,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)  static void dac33_calculate_times(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	unsigned int period_size = substream->runtime->period_size;  	unsigned int rate = substream->runtime->rate; @@ -1129,8 +1120,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,  			     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; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; @@ -1163,8 +1153,7 @@ static snd_pcm_sframes_t dac33_dai_delay(  			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; +	struct snd_soc_codec *codec = rtd->codec;  	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	unsigned long long t0, t1, t_now;  	unsigned int time_delta, uthr; @@ -1389,24 +1378,47 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,  	return 0;  } -static int dac33_soc_probe(struct platform_device *pdev) +static int dac33_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct tlv320dac33_priv *dac33; +	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; -	BUG_ON(!tlv320dac33_codec); +	codec->control_data = dac33->control_data; +	codec->hw_write = (hw_write_t) i2c_master_send; +	codec->bias_level = SND_SOC_BIAS_OFF; +	codec->idle_bias_off = 1; +	dac33->codec = codec; -	codec = tlv320dac33_codec; -	socdev->card->codec = codec; -	dac33 = snd_soc_codec_get_drvdata(codec); +	/* Read the tlv320dac33 ID registers */ +	ret = dac33_hard_power(codec, 1); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to power up codec: %d\n", ret); +		goto err_power; +	} +	dac33_read_id(codec); +	dac33_hard_power(codec, 0); -	/* 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"); -		goto pcm_err; +	/* Check if the IRQ number is valid and request it */ +	if (dac33->irq >= 0) { +		ret = request_irq(dac33->irq, dac33_interrupt_handler, +				  IRQF_TRIGGER_RISING | IRQF_DISABLED, +				  codec->name, codec); +		if (ret < 0) { +			dev_err(codec->dev, "Could not request IRQ%d (%d)\n", +						dac33->irq, ret); +			dac33->irq = -1; +		} +		if (dac33->irq != -1) { +			/* Setup work queue */ +			dac33->dac33_wq = +				create_singlethread_workqueue("tlv320dac33"); +			if (dac33->dac33_wq == NULL) { +				free_irq(dac33->irq, codec); +				return -ENOMEM; +			} + +			INIT_WORK(&dac33->work, dac33_work); +		}  	}  	snd_soc_add_controls(codec, dac33_snd_controls, @@ -1420,56 +1432,51 @@ static int dac33_soc_probe(struct platform_device *pdev)  			snd_soc_add_controls(codec, dac33_fifo_snd_controls,  					ARRAY_SIZE(dac33_fifo_snd_controls));  	} -  	dac33_add_widgets(codec); -	return 0; - -pcm_err: -	dac33_hard_power(codec, 0); +err_power:  	return ret;  } -static int dac33_soc_remove(struct platform_device *pdev) +static int dac33_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; +	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);  	dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - +	if (dac33->irq >= 0) { +		free_irq(dac33->irq, dac33->codec); +		destroy_workqueue(dac33->dac33_wq); +	}  	return 0;  } -static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) +static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int dac33_soc_resume(struct platform_device *pdev) +static int dac33_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { +static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { +	.read = dac33_read_reg_cache, +	.write = dac33_write_locked, +	.set_bias_level = dac33_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(dac33_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default = dac33_reg,  	.probe = dac33_soc_probe,  	.remove = dac33_soc_remove,  	.suspend = dac33_soc_suspend,  	.resume = dac33_soc_resume,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);  #define DAC33_RATES	(SNDRV_PCM_RATE_44100 | \  			 SNDRV_PCM_RATE_48000) @@ -1485,8 +1492,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = {  	.set_fmt	= dac33_set_dai_fmt,  }; -struct snd_soc_dai dac33_dai = { -	.name = "tlv320dac33", +static struct snd_soc_dai_driver dac33_dai = { +	.name = "tlv320dac33-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -1495,14 +1502,12 @@ struct snd_soc_dai dac33_dai = {  		.formats = DAC33_FORMATS,},  	.ops = &dac33_dai_ops,  }; -EXPORT_SYMBOL_GPL(dac33_dai);  static int __devinit dac33_i2c_probe(struct i2c_client *client,  				     const struct i2c_device_id *id)  {  	struct tlv320dac33_platform_data *pdata;  	struct tlv320dac33_priv *dac33; -	struct snd_soc_codec *codec;  	int ret, i;  	if (client->dev.platform_data == NULL) { @@ -1515,33 +1520,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,  	if (dac33 == NULL)  		return -ENOMEM; -	codec = &dac33->codec; -	snd_soc_codec_set_drvdata(codec, dac33); -	codec->control_data = client; - -	mutex_init(&codec->mutex); +	dac33->control_data = client;  	mutex_init(&dac33->mutex);  	spin_lock_init(&dac33->lock); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "tlv320dac33"; -	codec->owner = THIS_MODULE; -	codec->read = dac33_read_reg_cache; -	codec->write = dac33_write_locked; -	codec->hw_write = (hw_write_t) i2c_master_send; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = dac33_set_bias_level; -	codec->idle_bias_off = 1; -	codec->dai = &dac33_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(dac33_reg); -	codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), -				   GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto error_reg; -	}  	i2c_set_clientdata(client, dac33); @@ -1561,125 +1542,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,  	/* Disable FIFO use by default */  	dac33->fifo_mode = DAC33_FIFO_BYPASS; -	tlv320dac33_codec = codec; - -	codec->dev = &client->dev; -	dac33_dai.dev = codec->dev; -  	/* Check if the reset GPIO number is valid and request it */  	if (dac33->power_gpio >= 0) {  		ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");  		if (ret < 0) { -			dev_err(codec->dev, +			dev_err(&client->dev,  				"Failed to request reset GPIO (%d)\n",  				dac33->power_gpio); -			snd_soc_unregister_dai(&dac33_dai); -			snd_soc_unregister_codec(codec); -			goto error_gpio; +			goto err_gpio;  		}  		gpio_direction_output(dac33->power_gpio, 0);  	} -	/* Check if the IRQ number is valid and request it */ -	if (dac33->irq >= 0) { -		ret = request_irq(dac33->irq, dac33_interrupt_handler, -				  IRQF_TRIGGER_RISING | IRQF_DISABLED, -				  codec->name, codec); -		if (ret < 0) { -			dev_err(codec->dev, "Could not request IRQ%d (%d)\n", -						dac33->irq, ret); -			dac33->irq = -1; -		} -		if (dac33->irq != -1) { -			/* Setup work queue */ -			dac33->dac33_wq = -				create_singlethread_workqueue("tlv320dac33"); -			if (dac33->dac33_wq == NULL) { -				free_irq(dac33->irq, &dac33->codec); -				ret = -ENOMEM; -				goto error_wq; -			} - -			INIT_WORK(&dac33->work, dac33_work); -		} -	} -  	for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)  		dac33->supplies[i].supply = dac33_supply_names[i]; -	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), +	ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),  				 dac33->supplies);  	if (ret != 0) { -		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); +		dev_err(&client->dev, "Failed to request supplies: %d\n", ret);  		goto err_get;  	} -	/* Read the tlv320dac33 ID registers */ -	ret = dac33_hard_power(codec, 1); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to power up codec: %d\n", ret); -		goto error_codec; -	} -	dac33_read_id(codec); -	dac33_hard_power(codec, 0); - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto error_codec; -	} - -	ret = snd_soc_register_dai(&dac33_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		goto error_codec; -	} +	ret = snd_soc_register_codec(&client->dev, +			&soc_codec_dev_tlv320dac33, &dac33_dai, 1); +	if (ret < 0) +		goto err_register;  	return ret; - -error_codec: +err_register:  	regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);  err_get: -	if (dac33->irq >= 0) { -		free_irq(dac33->irq, &dac33->codec); -		destroy_workqueue(dac33->dac33_wq); -	} -error_wq:  	if (dac33->power_gpio >= 0)  		gpio_free(dac33->power_gpio); -error_gpio: -	kfree(codec->reg_cache); -error_reg: -	tlv320dac33_codec = NULL; +err_gpio:  	kfree(dac33); -  	return ret;  }  static int __devexit dac33_i2c_remove(struct i2c_client *client)  { -	struct tlv320dac33_priv *dac33; - -	dac33 = i2c_get_clientdata(client); +	struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);  	if (unlikely(dac33->chip_power)) -		dac33_hard_power(&dac33->codec, 0); +		dac33_hard_power(dac33->codec, 0);  	if (dac33->power_gpio >= 0)  		gpio_free(dac33->power_gpio); -	if (dac33->irq >= 0) -		free_irq(dac33->irq, &dac33->codec);  	regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); -	destroy_workqueue(dac33->dac33_wq); -	snd_soc_unregister_dai(&dac33_dai); -	snd_soc_unregister_codec(&dac33->codec); -	kfree(dac33->codec.reg_cache); +	snd_soc_unregister_codec(&client->dev);  	kfree(dac33); -	tlv320dac33_codec = NULL;  	return 0;  } @@ -1694,7 +1609,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {  static struct i2c_driver tlv320dac33_i2c_driver = {  	.driver = { -		.name = "tlv320dac33", +		.name = "tlv320dac33-codec",  		.owner = THIS_MODULE,  	},  	.probe		= dac33_i2c_probe, diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h index eb8ae07f0bd2..7c318b5da437 100644 --- a/sound/soc/codecs/tlv320dac33.h +++ b/sound/soc/codecs/tlv320dac33.h @@ -261,7 +261,4 @@  #define TLV320DAC33_MCLK		0  #define TLV320DAC33_SLEEPCLK		1 -extern struct snd_soc_dai dac33_dai; -extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33; -  #endif /* __TLV320DAC33_H */ diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 7b618bbff884..c7ee1a4c9d99 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -36,7 +36,16 @@  #include <sound/initval.h>  #include <sound/tlv.h> -#include "twl4030.h" +/* Register descriptions are here */ +#include <linux/mfd/twl4030-codec.h> + +/* Shadow register used by the audio driver */ +#define TWL4030_REG_SW_SHADOW		0x4A +#define TWL4030_CACHEREGNUM	(TWL4030_REG_SW_SHADOW + 1) + +/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ +#define TWL4030_HFL_EN			0x01 +#define TWL4030_HFR_EN			0x02  /*   * twl4030 register cache & default register settings @@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)  } -static void twl4030_init_chip(struct platform_device *pdev) +static void twl4030_init_chip(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct twl4030_setup_data *setup = socdev->codec_data; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	u8 reg, byte;  	int i = 0;  	/* Check defaults, if instructed before anything else */ -	if (setup && setup->check_defaults) +	if (pdata && pdata->check_defaults)  		twl4030_check_defaults(codec);  	/* Reset registers, if no setup data or if instructed to do so */ -	if (!setup || (setup && setup->reset_registers)) +	if (!pdata || (pdata && pdata->reset_registers))  		twl4030_reset_registers(codec);  	/* Refresh APLL_CTL register from HW */ @@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev)  	twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);  	/* Machine dependent setup */ -	if (!setup) +	if (!pdata)  		return; -	twl4030->digimic_delay = setup->digimic_delay; - -	/* Configuration for headset ramp delay from setup data */ -	if (setup->sysclk != twl4030->sysclk) -		dev_warn(codec->dev, -				"Mismatch in APLL mclk: %u (configured: %u)\n", -				setup->sysclk, twl4030->sysclk); +	twl4030->digimic_delay = pdata->digimic_delay;  	reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);  	reg &= ~TWL4030_RAMP_DELAY; -	reg |= (setup->ramp_delay_value << 2); +	reg |= (pdata->ramp_delay_value << 2);  	twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);  	/* initiate offset cancellation */ @@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev)  	reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);  	reg &= ~TWL4030_OFFSET_CNCL_SEL; -	reg |= setup->offset_cncl_path; +	reg |= pdata->offset_cncl_path;  	twl4030_write(codec, TWL4030_REG_ANAMICL,  		reg | TWL4030_CNCL_OFFSET_START); @@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w,  static void headset_ramp(struct snd_soc_codec *codec, int ramp)  { -	struct snd_soc_device *socdev = codec->socdev; -	struct twl4030_setup_data *setup = socdev->codec_data; - +	struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;  	unsigned char hs_gain, hs_pop;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	/* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)  	/* Enable external mute control, this dramatically reduces  	 * the pop-noise */ -	if (setup && setup->hs_extmute) { -		if (setup->set_hs_extmute) { -			setup->set_hs_extmute(1); +	if (pdata && pdata->hs_extmute) { +		if (pdata->set_hs_extmute) { +			pdata->set_hs_extmute(1);  		} else {  			hs_pop |= TWL4030_EXTMUTE;  			twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); @@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)  	}  	/* Disable external mute */ -	if (setup && setup->hs_extmute) { -		if (setup->set_hs_extmute) { -			setup->set_hs_extmute(0); +	if (pdata && pdata->hs_extmute) { +		if (pdata->set_hs_extmute) { +			pdata->set_hs_extmute(0);  		} else {  			hs_pop &= ~TWL4030_EXTMUTE;  			twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); @@ -1707,8 +1706,7 @@ static int twl4030_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	if (twl4030->master_substream) { @@ -1738,8 +1736,7 @@ static void twl4030_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	if (twl4030->master_substream == substream) @@ -1764,8 +1761,7 @@ static int twl4030_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	u8 mode, old_mode, format, old_format; @@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	u8 mode; @@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	/* Enable voice digital filters */  	twl4030_voice_enable(codec, substream->stream, 0); @@ -2044,8 +2038,7 @@ static int twl4030_voice_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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);  	u8 old_mode, mode; @@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)  #define TWL4030_RATES	 (SNDRV_PCM_RATE_8000_48000)  #define TWL4030_FORMATS	 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) -static struct snd_soc_dai_ops twl4030_dai_ops = { +static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {  	.startup	= twl4030_startup,  	.shutdown	= twl4030_shutdown,  	.hw_params	= twl4030_hw_params, @@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {  	.set_tristate	= twl4030_voice_set_tristate,  }; -struct snd_soc_dai twl4030_dai[] = { +static struct snd_soc_dai_driver twl4030_dai[] = {  { -	.name = "twl4030", +	.name = "twl4030-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 2, @@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = {  		.channels_max = 4,  		.rates = TWL4030_RATES,  		.formats = TWL4030_FORMATS,}, -	.ops = &twl4030_dai_ops, +	.ops = &twl4030_dai_hifi_ops,  },  { -	.name = "twl4030 Voice", +	.name = "twl4030-voice",  	.playback = {  		.stream_name = "Voice Playback",  		.channels_min = 1, @@ -2227,164 +2220,92 @@ struct snd_soc_dai twl4030_dai[] = {  	.ops = &twl4030_dai_voice_ops,  },  }; -EXPORT_SYMBOL_GPL(twl4030_dai); -static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) +static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); -  	return 0;  } -static int twl4030_soc_resume(struct platform_device *pdev) +static int twl4030_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -static struct snd_soc_codec *twl4030_codec; - -static int twl4030_soc_probe(struct platform_device *pdev) +static int twl4030_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret; - -	BUG_ON(!twl4030_codec); - -	codec = twl4030_codec; -	socdev->card->codec = codec; - -	twl4030_init_chip(pdev); +	struct twl4030_priv *twl4030; -	/* 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"); -		return ret; +	twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); +	if (twl4030 == NULL) { +		printk("Can not allocate memroy\n"); +		return -ENOMEM;  	} +	snd_soc_codec_set_drvdata(codec, twl4030); +	/* Set the defaults, and power up the codec */ +	twl4030->sysclk = twl4030_codec_get_mclk() / 1000; +	codec->bias_level = SND_SOC_BIAS_OFF; +	codec->idle_bias_off = 1; + +	twl4030_init_chip(codec);  	snd_soc_add_controls(codec, twl4030_snd_controls,  				ARRAY_SIZE(twl4030_snd_controls));  	twl4030_add_widgets(codec); -  	return 0;  } -static int twl4030_soc_remove(struct platform_device *pdev) +static int twl4030_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	/* Reset registers to their chip default before leaving */  	twl4030_reset_registers(codec);  	twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); -  	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { +	.probe = twl4030_soc_probe, +	.remove = twl4030_soc_remove, +	.suspend = twl4030_soc_suspend, +	.resume = twl4030_soc_resume, +	.read = twl4030_read_reg_cache, +	.write = twl4030_write, +	.set_bias_level = twl4030_set_bias_level, +	.reg_cache_size = sizeof(twl4030_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default = twl4030_reg, +}; +  static int __devinit twl4030_codec_probe(struct platform_device *pdev)  {  	struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; -	struct snd_soc_codec *codec; -	struct twl4030_priv *twl4030; -	int ret;  	if (!pdata) {  		dev_err(&pdev->dev, "platform_data is missing\n");  		return -EINVAL;  	} -	twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); -	if (twl4030 == NULL) { -		dev_err(&pdev->dev, "Can not allocate memroy\n"); -		return -ENOMEM; -	} - -	codec = &twl4030->codec; -	snd_soc_codec_set_drvdata(codec, twl4030); -	codec->dev = &pdev->dev; -	twl4030_dai[0].dev = &pdev->dev; -	twl4030_dai[1].dev = &pdev->dev; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "twl4030"; -	codec->owner = THIS_MODULE; -	codec->read = twl4030_read_reg_cache; -	codec->write = twl4030_write; -	codec->set_bias_level = twl4030_set_bias_level; -	codec->idle_bias_off = 1; -	codec->dai = twl4030_dai; -	codec->num_dai = ARRAY_SIZE(twl4030_dai); -	codec->reg_cache_size = sizeof(twl4030_reg); -	codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), -					GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto error_cache; -	} - -	platform_set_drvdata(pdev, twl4030); -	twl4030_codec = codec; - -	/* Set the defaults, and power up the codec */ -	twl4030->sysclk = twl4030_codec_get_mclk() / 1000; -	codec->bias_level = SND_SOC_BIAS_OFF; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto error_codec; -	} - -	ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		snd_soc_unregister_codec(codec); -		goto error_codec; -	} - -	return 0; - -error_codec: -	twl4030_codec_enable(codec, 0); -	kfree(codec->reg_cache); -error_cache: -	kfree(twl4030); -	return ret; +	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, +			twl4030_dai, ARRAY_SIZE(twl4030_dai));  }  static int __devexit twl4030_codec_remove(struct platform_device *pdev)  { -	struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); +	struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev); -	snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); -	snd_soc_unregister_codec(&twl4030->codec); -	kfree(twl4030->codec.reg_cache); +	snd_soc_unregister_codec(&pdev->dev);  	kfree(twl4030); - -	twl4030_codec = NULL;  	return 0;  } -MODULE_ALIAS("platform:twl4030_codec_audio"); +MODULE_ALIAS("platform:twl4030-codec");  static struct platform_driver twl4030_codec_driver = {  	.probe		= twl4030_codec_probe,  	.remove		= __devexit_p(twl4030_codec_remove),  	.driver		= { -		.name	= "twl4030_codec_audio", +		.name	= "twl4030-codec",  		.owner	= THIS_MODULE,  	},  }; @@ -2401,14 +2322,6 @@ static void __exit twl4030_exit(void)  }  module_exit(twl4030_exit); -struct snd_soc_codec_device soc_codec_dev_twl4030 = { -	.probe = twl4030_soc_probe, -	.remove = twl4030_soc_remove, -	.suspend = twl4030_soc_suspend, -	.resume = twl4030_soc_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); -  MODULE_DESCRIPTION("ASoC TWL4030 codec driver");  MODULE_AUTHOR("Steve Sakoman");  MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h deleted file mode 100644 index 6c57430f6e24..000000000000 --- a/sound/soc/codecs/twl4030.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ALSA SoC TWL4030 codec driver - * - * Author: Steve Sakoman <steve@sakoman.com> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __TWL4030_AUDIO_H__ -#define __TWL4030_AUDIO_H__ - -/* Register descriptions are here */ -#include <linux/mfd/twl4030-codec.h> - -/* Shadow register used by the audio driver */ -#define TWL4030_REG_SW_SHADOW		0x4A -#define TWL4030_CACHEREGNUM	(TWL4030_REG_SW_SHADOW + 1) - -/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ -#define TWL4030_HFL_EN			0x01 -#define TWL4030_HFR_EN			0x02 - -#define TWL4030_DAI_HIFI		0 -#define TWL4030_DAI_VOICE		1 - -extern struct snd_soc_dai twl4030_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_twl4030; - -struct twl4030_setup_data { -	unsigned int ramp_delay_value; -	unsigned int digimic_delay; /* in ms */ -	unsigned int sysclk; -	unsigned int offset_cncl_path; -	unsigned int check_defaults:1; -	unsigned int reset_registers:1; -	unsigned int hs_extmute:1; -	void (*set_hs_extmute)(int mute); -}; - -#endif	/* End of __TWL4030_AUDIO_H__ */ - - diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 64a807f1a8a1..10f6e5214511 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -45,7 +45,6 @@  /* codec private data */  struct twl6040_data { -	struct snd_soc_codec codec;  	int audpwron;  	int naudint;  	int codec_powered; @@ -770,8 +769,7 @@ static int twl6040_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);  	if (!priv->sysclk) { @@ -803,8 +801,7 @@ static int twl6040_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);  	u8 lppllctl;  	int rate; @@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream,  			int cmd, 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; +	struct snd_soc_codec *codec = rtd->codec;  	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);  	switch (cmd) { @@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {  	.set_sysclk	= twl6040_set_dai_sysclk,  }; -struct snd_soc_dai twl6040_dai = { -	.name = "twl6040", +static struct snd_soc_dai_driver twl6040_dai = { +	.name = "twl6040-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = {  	},  	.ops = &twl6040_dai_ops,  }; -EXPORT_SYMBOL_GPL(twl6040_dai);  #ifdef CONFIG_PM -static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) +static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int twl6040_resume(struct platform_device *pdev) +static int twl6040_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev)  #define twl6040_resume NULL  #endif -static struct snd_soc_codec *twl6040_codec; - -static int twl6040_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	BUG_ON(!twl6040_codec); - -	codec = twl6040_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"); -		return ret; -	} - -	snd_soc_add_controls(codec, twl6040_snd_controls, -				ARRAY_SIZE(twl6040_snd_controls)); -	twl6040_add_widgets(codec); - -	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); -	return ret; -} - -static int twl6040_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_twl6040 = { -	.probe = twl6040_probe, -	.remove = twl6040_remove, -	.suspend = twl6040_suspend, -	.resume = twl6040_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040); - -static int __devinit twl6040_codec_probe(struct platform_device *pdev) +static int twl6040_probe(struct snd_soc_codec *codec)  { -	struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; -	struct snd_soc_codec *codec; +	struct twl4030_codec_data *twl_codec = codec->dev->platform_data;  	struct twl6040_data *priv;  	int audpwron, naudint;  	int ret = 0; @@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)  	priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);  	if (priv == NULL)  		return -ENOMEM; +	snd_soc_codec_set_drvdata(codec, priv);  	if (twl_codec) {  		audpwron = twl_codec->audpwron_gpio; @@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)  	priv->audpwron = audpwron;  	priv->naudint = naudint; -	codec = &priv->codec; -	codec->dev = &pdev->dev; -	twl6040_dai.dev = &pdev->dev; - -	codec->name = "twl6040"; -	codec->owner = THIS_MODULE; -	codec->read = twl6040_read_reg_cache; -	codec->write = twl6040_write; -	codec->set_bias_level = twl6040_set_bias_level; -	snd_soc_codec_set_drvdata(codec, priv); -	codec->dai = &twl6040_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(twl6040_reg); -	codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg), -					GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths);  	init_completion(&priv->ready);  	if (gpio_is_valid(audpwron)) { @@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)  	if (ret)  		goto irq_err; -	ret = snd_soc_register_codec(codec); -	if (ret) -		goto reg_err; - -	twl6040_codec = codec; - -	ret = snd_soc_register_dai(&twl6040_dai); -	if (ret) -		goto dai_err; +	snd_soc_add_controls(codec, twl6040_snd_controls, +				ARRAY_SIZE(twl6040_snd_controls)); +	twl6040_add_widgets(codec);  	return 0; -dai_err: -	snd_soc_unregister_codec(codec); -	twl6040_codec = NULL; -reg_err: -	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);  irq_err:  	if (naudint)  		free_irq(naudint, codec); @@ -1193,36 +1090,57 @@ gpio2_err:  	if (gpio_is_valid(audpwron))  		gpio_free(audpwron);  gpio1_err: -	kfree(codec->reg_cache); -cache_err:  	kfree(priv);  	return ret;  } -static int __devexit twl6040_codec_remove(struct platform_device *pdev) +static int twl6040_remove(struct snd_soc_codec *codec)  { -	struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); +	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);  	int audpwron = priv->audpwron;  	int naudint = priv->naudint; +	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); +  	if (gpio_is_valid(audpwron))  		gpio_free(audpwron);  	if (naudint) -		free_irq(naudint, twl6040_codec); +		free_irq(naudint, codec); -	snd_soc_unregister_dai(&twl6040_dai); -	snd_soc_unregister_codec(twl6040_codec); +	kfree(priv); -	kfree(twl6040_codec); -	twl6040_codec = NULL; +	return 0; +} +static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { +	.probe = twl6040_probe, +	.remove = twl6040_remove, +	.suspend = twl6040_suspend, +	.resume = twl6040_resume, +	.read = twl6040_read_reg_cache, +	.write = twl6040_write, +	.set_bias_level = twl6040_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(twl6040_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_default = twl6040_reg, +}; + +static int __devinit twl6040_codec_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_twl6040, &twl6040_dai, 1); +} + +static int __devexit twl6040_codec_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  }  static struct platform_driver twl6040_codec_driver = {  	.driver = { -		.name = "twl6040_codec", +		.name = "twl6040-codec",  		.owner = THIS_MODULE,  	},  	.probe = twl6040_codec_probe, diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index c472070a1da2..f7c77fa58a3c 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h @@ -135,7 +135,4 @@  #define TWL6040_HPPLL_ID		1  #define TWL6040_LPPLL_ID		2 -extern struct snd_soc_dai twl6040_dai; -extern struct snd_soc_codec_device soc_codec_dev_twl6040; -  #endif /* End of __TWL6040_H__ */ diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index f3b4c1d6a82d..7540a509a6f5 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -161,8 +161,7 @@ static int uda134x_startup(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; +	struct snd_soc_codec *codec =rtd->codec;  	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);  	struct snd_pcm_runtime *master_runtime; @@ -194,8 +193,7 @@ static void uda134x_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);  	if (uda134x->master_substream == substream) @@ -209,8 +207,7 @@ static int uda134x_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);  	u8 hw_params; @@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,  			pd->power(1);  			/* Sync reg_cache with the hardware */  			for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) -				codec->write(codec, i, *cache++); +				codec->driver->write(codec, i, *cache++);  		}  		break;  	case SND_SOC_BIAS_STANDBY: @@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = {  	.set_fmt	= uda134x_set_dai_fmt,  }; -struct snd_soc_dai uda134x_dai = { -	.name = "UDA134X", +static struct snd_soc_dai_driver uda134x_dai = { +	.name = "uda134x-hifi",  	/* playback capabilities */  	.playback = {  		.stream_name = "Playback", @@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = {  	/* pcm operations */  	.ops = &uda134x_dai_ops,  }; -EXPORT_SYMBOL(uda134x_dai); - -static int uda134x_soc_probe(struct platform_device *pdev) +static int uda134x_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec;  	struct uda134x_priv *uda134x; -	void *codec_setup_data = socdev->codec_data; -	int ret = -ENOMEM; -	struct uda134x_platform_data *pd; +	struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev); +	int ret;  	printk(KERN_INFO "UDA134X SoC Audio Codec\n"); -	if (!codec_setup_data) { +	if (!pd) {  		printk(KERN_ERR "UDA134X SoC codec: "  		       "missing L3 bitbang function\n");  		return -ENODEV;  	} -	pd = codec_setup_data;  	switch (pd->model) {  	case UDA134X_UDA1340:  	case UDA134X_UDA1341: @@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)  		return -EINVAL;  	} -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (socdev->card->codec == NULL) -		return ret; - -	codec = socdev->card->codec; -  	uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);  	if (uda134x == NULL) -		goto priv_err; +		return -ENOMEM;  	snd_soc_codec_set_drvdata(codec, uda134x); -	codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), -				   GFP_KERNEL); -	if (codec->reg_cache == NULL) -		goto reg_err; - -	mutex_init(&codec->mutex); - -	codec->reg_cache_size = sizeof(uda134x_reg); -	codec->reg_cache_step = 1; - -	codec->name = "UDA134X"; -	codec->owner = THIS_MODULE; -	codec->dai = &uda134x_dai; -	codec->num_dai = 1; -	codec->read = uda134x_read_reg_cache; -	codec->write = uda134x_write; - -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->control_data = codec_setup_data; +	codec->control_data = pd;  	if (pd->power)  		pd->power(1);  	uda134x_reset(codec); -	if (pd->is_powered_on_standby) { -		codec->set_bias_level = NULL; +	if (pd->is_powered_on_standby)  		uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); -	} else { -		codec->set_bias_level = uda134x_set_bias_level; +	else  		uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	} - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "UDA134X: failed to register pcms\n"); -		goto pcm_err; -	}  	switch (pd->model) {  	case UDA134X_UDA1340: @@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev)  	default:  		printk(KERN_ERR "%s unknown codec type: %d",  			__func__, pd->model); -	return -EINVAL; +		kfree(uda134x); +		return -EINVAL;  	}  	if (ret < 0) {  		printk(KERN_ERR "UDA134X: failed to register controls\n"); -		goto pcm_err; +		kfree(uda134x); +		return ret;  	}  	return 0; - -pcm_err: -	kfree(codec->reg_cache); -reg_err: -	kfree(snd_soc_codec_get_drvdata(codec)); -priv_err: -	kfree(codec); -	return ret;  }  /* power down chip */ -static int uda134x_soc_remove(struct platform_device *pdev) +static int uda134x_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; +	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);  	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec->reg_cache); -	kfree(codec); - +	kfree(uda134x);  	return 0;  }  #if defined(CONFIG_PM) -static int uda134x_soc_suspend(struct platform_device *pdev, +static int uda134x_soc_suspend(struct snd_soc_codec *codec,  						pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int uda134x_soc_resume(struct platform_device *pdev) +static int uda134x_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);  	uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);  	return 0; @@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev)  #define uda134x_soc_resume NULL  #endif /* CONFIG_PM */ -struct snd_soc_codec_device soc_codec_dev_uda134x = { +static struct snd_soc_codec_driver soc_codec_dev_uda134x = {  	.probe =        uda134x_soc_probe,  	.remove =       uda134x_soc_remove,  	.suspend =      uda134x_soc_suspend,  	.resume =       uda134x_soc_resume, +	.reg_cache_size = sizeof(uda134x_reg), +	.reg_word_size = sizeof(u8), +	.reg_cache_step = 1, +	.read = uda134x_read_reg_cache, +	.write = uda134x_write, +#ifdef POWER_OFF_ON_STANDBY +	.set_bias_level = uda134x_set_bias_level, +#endif +}; + +static int __devinit uda134x_codec_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_uda134x, &uda134x_dai, 1); +} + +static int __devexit uda134x_codec_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver uda134x_codec_driver = { +	.driver = { +		.name = "uda134x-codec", +		.owner = THIS_MODULE, +	}, +	.probe = uda134x_codec_probe, +	.remove = __devexit_p(uda134x_codec_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x); -static int __init uda134x_init(void) +static int __init uda134x_codec_init(void)  { -	return snd_soc_register_dai(&uda134x_dai); +	return platform_driver_register(&uda134x_codec_driver);  } -module_init(uda134x_init); +module_init(uda134x_codec_init); -static void __exit uda134x_exit(void) +static void __exit uda134x_codec_exit(void)  { -	snd_soc_unregister_dai(&uda134x_dai); +	platform_driver_unregister(&uda134x_codec_driver);  } -module_exit(uda134x_exit); +module_exit(uda134x_codec_exit);  MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");  MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h index 205f03b3eaf8..9faae06972b3 100644 --- a/sound/soc/codecs/uda134x.h +++ b/sound/soc/codecs/uda134x.h @@ -31,7 +31,4 @@  #define STATUS0_DAIFMT_MASK (~(7<<1))  #define STATUS0_SYSCLK_MASK (~(3<<4)) -extern struct snd_soc_dai uda134x_dai; -extern struct snd_soc_codec_device soc_codec_dev_uda134x; -  #endif diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 2f925a27dcde..1a51c816e542 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -33,11 +33,9 @@  #include "uda1380.h" -static struct snd_soc_codec *uda1380_codec; -  /* codec private data */  struct uda1380_priv { -	struct snd_soc_codec codec; +	struct snd_soc_codec *codec;  	u16 reg_cache[UDA1380_CACHEREGNUM];  	unsigned int dac_clk;  	struct work_struct work; @@ -135,6 +133,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,  static void uda1380_flush_work(struct work_struct *work)  { +	struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); +	struct snd_soc_codec *uda1380_codec = uda1380->codec;  	int bit, reg;  	for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { @@ -145,6 +145,7 @@ static void uda1380_flush_work(struct work_struct *work)  				uda1380_read_reg_cache(uda1380_codec, reg));  		clear_bit(bit, &uda1380_cache_dirty);  	} +  }  /* declarations of ALSA reg_elem_REAL controls */ @@ -474,8 +475,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,  		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; +	struct snd_soc_codec *codec = rtd->codec;  	struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);  	int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); @@ -501,8 +501,7 @@ static int uda1380_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);  	/* set WSPLL power and divider if running from this clock */ @@ -540,8 +539,7 @@ static void uda1380_pcm_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);  	/* shut down WSPLL power if running from this clock */ @@ -604,9 +602,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = {  	.set_fmt	= uda1380_set_dai_fmt_capture,  }; -struct snd_soc_dai uda1380_dai[] = { +static struct snd_soc_dai_driver uda1380_dai[] = {  { -	.name = "UDA1380", +	.name = "uda1380-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -622,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = {  	.ops = &uda1380_dai_ops,  },  { /* playback only - dual interface */ -	.name = "UDA1380", +	.name = "uda1380-hifi-playback",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -633,7 +631,7 @@ struct snd_soc_dai uda1380_dai[] = {  	.ops = &uda1380_dai_ops_playback,  },  { /* capture only - dual interface*/ -	.name = "UDA1380", +	.name = "uda1380-hifi-capture",  	.capture = {  		.stream_name = "Capture",  		.channels_min = 1, @@ -644,21 +642,15 @@ struct snd_soc_dai uda1380_dai[] = {  	.ops = &uda1380_dai_ops_capture,  },  }; -EXPORT_SYMBOL_GPL(uda1380_dai); -static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) +static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int uda1380_resume(struct platform_device *pdev) +static int uda1380_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -673,91 +665,20 @@ static int uda1380_resume(struct platform_device *pdev)  	return 0;  } -static int uda1380_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct uda1380_platform_data *pdata; -	int ret = 0; - -	if (uda1380_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = uda1380_codec; -	codec = uda1380_codec; -	pdata = codec->dev->platform_data; - -	/* 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: %d\n", ret); -		goto pcm_err; -	} - -	/* power on device */ -	uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	/* set clock input */ -	switch (pdata->dac_clk) { -	case UDA1380_DAC_CLK_SYSCLK: -		uda1380_write(codec, UDA1380_CLK, 0); -		break; -	case UDA1380_DAC_CLK_WSPLL: -		uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); -		break; -	} - -	snd_soc_add_controls(codec, uda1380_snd_controls, -				ARRAY_SIZE(uda1380_snd_controls)); -	uda1380_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -/* power down chip */ -static int uda1380_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_uda1380 = { -	.probe = 	uda1380_probe, -	.remove = 	uda1380_remove, -	.suspend = 	uda1380_suspend, -	.resume =	uda1380_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); - -static int uda1380_register(struct uda1380_priv *uda1380) +static int uda1380_probe(struct snd_soc_codec *codec)  { -	int ret, i; -	struct snd_soc_codec *codec = &uda1380->codec; -	struct uda1380_platform_data *pdata = codec->dev->platform_data; +	struct uda1380_platform_data *pdata =codec->dev->platform_data; +	struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); +	int ret; -	if (uda1380_codec) { -		dev_err(codec->dev, "Another UDA1380 is registered\n"); -		return -EINVAL; -	} +	codec->hw_write = (hw_write_t)i2c_master_send;  	if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)  		return -EINVAL;  	ret = gpio_request(pdata->gpio_power, "uda1380 power");  	if (ret) -		goto err_out; +		return ret;  	ret = gpio_request(pdata->gpio_reset, "uda1380 reset");  	if (ret)  		goto err_gpio; @@ -769,25 +690,6 @@ static int uda1380_register(struct uda1380_priv *uda1380)  	udelay(5);  	gpio_set_value(pdata->gpio_reset, 0); -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, uda1380); -	codec->name = "UDA1380"; -	codec->owner = THIS_MODULE; -	codec->read = uda1380_read_reg_cache; -	codec->write = uda1380_write; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = uda1380_set_bias_level; -	codec->dai = uda1380_dai; -	codec->num_dai = ARRAY_SIZE(uda1380_dai); -	codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); -	codec->reg_cache = &uda1380->reg_cache; -	codec->reg_cache_step = 1; - -	memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); -  	ret = uda1380_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); @@ -796,83 +698,84 @@ static int uda1380_register(struct uda1380_priv *uda1380)  	INIT_WORK(&uda1380->work, uda1380_flush_work); -	for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) -		uda1380_dai[i].dev = codec->dev; - -	uda1380_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_reset; +	/* power on device */ +	uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +	/* set clock input */ +	switch (pdata->dac_clk) { +	case UDA1380_DAC_CLK_SYSCLK: +		uda1380_write(codec, UDA1380_CLK, 0); +		break; +	case UDA1380_DAC_CLK_WSPLL: +		uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); +		break;  	} -	ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		goto err_dai; -	} +	snd_soc_add_controls(codec, uda1380_snd_controls, +				ARRAY_SIZE(uda1380_snd_controls)); +	uda1380_add_widgets(codec);  	return 0; -err_dai: -	snd_soc_unregister_codec(codec);  err_reset:  	gpio_set_value(pdata->gpio_power, 0);  	gpio_free(pdata->gpio_reset);  err_gpio:  	gpio_free(pdata->gpio_power); -err_out:  	return ret;  } -static void uda1380_unregister(struct uda1380_priv *uda1380) +/* power down chip */ +static int uda1380_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = &uda1380->codec; -	struct uda1380_platform_data *pdata = codec->dev->platform_data; +	struct uda1380_platform_data *pdata =codec->dev->platform_data; -	snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); -	snd_soc_unregister_codec(&uda1380->codec); +	uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);  	gpio_set_value(pdata->gpio_power, 0);  	gpio_free(pdata->gpio_reset);  	gpio_free(pdata->gpio_power); -	kfree(uda1380); -	uda1380_codec = NULL; +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { +	.probe =	uda1380_probe, +	.remove =	uda1380_remove, +	.suspend =	uda1380_suspend, +	.resume =	uda1380_resume, +	.read = uda1380_read_reg_cache, +	.write = uda1380_write, +	.set_bias_level = uda1380_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(uda1380_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = uda1380_reg, +	.reg_cache_step = 1, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct uda1380_priv *uda1380; -	struct snd_soc_codec *codec;  	int ret;  	uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);  	if (uda1380 == NULL)  		return -ENOMEM; -	codec = &uda1380->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, uda1380); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; -	ret = uda1380_register(uda1380); -	if (ret != 0) +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); +	if (ret < 0)  		kfree(uda1380); -  	return ret;  }  static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)  { -	struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); -	uda1380_unregister(uda1380); +	snd_soc_unregister_codec(&i2c->dev); +	kfree(i2c_get_clientdata(i2c));  	return 0;  } @@ -884,7 +787,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);  static struct i2c_driver uda1380_i2c_driver = {  	.driver = { -		.name =  "UDA1380 I2C Codec", +		.name =  "uda1380-codec",  		.owner = THIS_MODULE,  	},  	.probe =    uda1380_i2c_probe, diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h index 9cefa8a54770..942e3927c72b 100644 --- a/sound/soc/codecs/uda1380.h +++ b/sound/soc/codecs/uda1380.h @@ -76,7 +76,4 @@  #define UDA1380_DAI_PLAYBACK	1 /* playback DAI */  #define UDA1380_DAI_CAPTURE	2 /* capture DAI */ -extern struct snd_soc_dai uda1380_dai[3]; -extern struct snd_soc_codec_device soc_codec_dev_uda1380; -  #endif /* _UDA1380_H */ diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index c18e261c3c7f..0b6f056f73cc 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h @@ -16,9 +16,6 @@ struct wm2000_setup_data {  extern int wm2000_add_controls(struct snd_soc_codec *codec); -extern struct snd_soc_dai wm2000_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm2000; -  #define WM2000_REG_SYS_START	    0x8000  #define WM2000_REG_SPEECH_CLARITY   0x8fef  #define WM2000_REG_SYS_WATCHDOG     0x8ff6 diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 0221ca79b3ae..f4f1fba38eb9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,  	return 0;  } -static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8350_resume(struct platform_device *pdev) +static int wm8350_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec,  }  EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); -static struct snd_soc_codec *wm8350_codec; +#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) + +#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ +			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, +}; + +static struct snd_soc_dai_driver wm8350_dai = { +	.name = "wm8350-hifi", +	.playback = { +		.stream_name = "Playback", +		.channels_min = 1, +		.channels_max = 2, +		.rates = WM8350_RATES, +		.formats = WM8350_FORMATS, +	}, +	.capture = { +		 .stream_name = "Capture", +		 .channels_min = 1, +		 .channels_max = 2, +		 .rates = WM8350_RATES, +		 .formats = WM8350_FORMATS, +	 }, +	.ops = &wm8350_dai_ops, +}; -static int wm8350_probe(struct platform_device *pdev) +static  int wm8350_codec_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct wm8350 *wm8350; +	struct wm8350 *wm8350 = dev_get_platdata(codec->dev);  	struct wm8350_data *priv; -	int ret;  	struct wm8350_output *out1;  	struct wm8350_output *out2; +	int ret, i; -	BUG_ON(!wm8350_codec); +	if (wm8350->codec.platform_data == NULL) { +		dev_err(codec->dev, "No audio platform data supplied\n"); +		return -EINVAL; +	} + +	priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); +	if (priv == NULL) +		return -ENOMEM; +	snd_soc_codec_set_drvdata(codec, priv); + +	for (i = 0; i < ARRAY_SIZE(supply_names); i++) +		priv->supplies[i].supply = supply_names[i]; + +	ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), +				 priv->supplies); +	if (ret != 0) +		goto err_priv; + +	wm8350->codec.codec = codec; +	codec->control_data = wm8350; -	socdev->card->codec = wm8350_codec; -	codec = socdev->card->codec; -	wm8350 = codec->control_data; -	priv = snd_soc_codec_get_drvdata(codec); +	/* Put the codec into reset if it wasn't already */ +	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); + +	INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);  	/* Enable the codec */  	wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); @@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev)  	wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,  			    wm8350_mic_handler, 0, "Microphone detect", priv); -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(&pdev->dev, "failed to create pcms\n"); -		return ret; -	}  	snd_soc_add_controls(codec, wm8350_snd_controls,  				ARRAY_SIZE(wm8350_snd_controls)); @@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev)  	wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; + +err_priv: +	kfree(priv); +	return ret;  } -static int wm8350_remove(struct platform_device *pdev) +static int  wm8350_codec_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -	struct wm8350 *wm8350 = codec->control_data;  	struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); +	struct wm8350 *wm8350 = dev_get_platdata(codec->dev);  	int ret;  	wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, @@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev)  	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); +	regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); +	kfree(priv);  	return 0;  } -#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) - -#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ -			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 = { -		.stream_name = "Playback", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8350_RATES, -		.formats = WM8350_FORMATS, -	}, -	.capture = { -		 .stream_name = "Capture", -		 .channels_min = 1, -		 .channels_max = 2, -		 .rates = WM8350_RATES, -		 .formats = WM8350_FORMATS, -	 }, -	.ops = &wm8350_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8350_dai); - -struct snd_soc_codec_device soc_codec_dev_wm8350 = { -	.probe = 	wm8350_probe, -	.remove = 	wm8350_remove, +static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { +	.probe =	wm8350_codec_probe, +	.remove =	wm8350_codec_remove,  	.suspend = 	wm8350_suspend,  	.resume =	wm8350_resume, +	.read = wm8350_codec_read, +	.write = wm8350_codec_write, +	.set_bias_level = wm8350_set_bias_level,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); -static __devinit int wm8350_codec_probe(struct platform_device *pdev) +static int __devinit wm8350_probe(struct platform_device *pdev)  { -	struct wm8350 *wm8350 = platform_get_drvdata(pdev); -	struct wm8350_data *priv; -	struct snd_soc_codec *codec; -	int ret, i; - -	if (wm8350->codec.platform_data == NULL) { -		dev_err(&pdev->dev, "No audio platform data supplied\n"); -		return -EINVAL; -	} - -	priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); -	if (priv == NULL) -		return -ENOMEM; - -	for (i = 0; i < ARRAY_SIZE(supply_names); i++) -		priv->supplies[i].supply = supply_names[i]; - -	ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), -				 priv->supplies); -	if (ret != 0) -		goto err_priv; - -	codec = &priv->codec; -	wm8350->codec.codec = codec; - -	wm8350_dai.dev = &pdev->dev; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	codec->dev = &pdev->dev; -	codec->name = "WM8350"; -	codec->owner = THIS_MODULE; -	codec->read = wm8350_codec_read; -	codec->write = wm8350_codec_write; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8350_set_bias_level; -	codec->dai = &wm8350_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8350_MAX_REGISTER; -	snd_soc_codec_set_drvdata(codec, priv); -	codec->control_data = wm8350; - -	/* Put the codec into reset if it wasn't already */ -	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); - -	INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); -	ret = snd_soc_register_codec(codec); -	if (ret != 0) -		goto err_supply; - -	wm8350_codec = codec; - -	ret = snd_soc_register_dai(&wm8350_dai); -	if (ret != 0) -		goto err_codec; -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err_supply: -	regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); -err_priv: -	kfree(priv); -	wm8350_codec = NULL; -	return ret; +	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350, +			&wm8350_dai, 1);  } -static int __devexit wm8350_codec_remove(struct platform_device *pdev) +static int __devexit wm8350_remove(struct platform_device *pdev)  { -	struct wm8350 *wm8350 = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = wm8350->codec.codec; -	struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - -	snd_soc_unregister_dai(&wm8350_dai); -	snd_soc_unregister_codec(codec); -	regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); -	kfree(priv); -	wm8350_codec = NULL; +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  } @@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = {  		   .name = "wm8350-codec",  		   .owner = THIS_MODULE,  		   }, -	.probe = wm8350_codec_probe, -	.remove = __devexit_p(wm8350_codec_remove), +	.probe = wm8350_probe, +	.remove = __devexit_p(wm8350_remove),  };  static __init int wm8350_init(void) diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index 9ed0467c71db..74108eb82938 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h @@ -15,9 +15,6 @@  #include <sound/soc.h>  #include <linux/mfd/wm8350/audio.h> -extern struct snd_soc_dai wm8350_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8350; -  enum wm8350_jack {  	WM8350_JDL = 1,  	WM8350_JDR = 2, diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 8f294066b0ed..850299786e02 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = {  /* codec private data */  struct wm8400_priv { -	struct snd_soc_codec codec; +	struct snd_soc_codec *codec;  	struct wm8400 *wm8400;  	u16 fake_register;  	unsigned int sysclk; @@ -1163,8 +1163,7 @@ static int wm8400_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);  	audio1 &= ~WM8400_AIF_WL_MASK; @@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = {   * 1. ADC/DAC on Primary Interface   * 2. ADC on Primary Interface/DAC on secondary   */ -struct snd_soc_dai wm8400_dai = { +static struct snd_soc_dai_driver wm8400_dai = {  /* ADC/DAC on primary */ -	.name = "WM8400 ADC/DAC Primary", -	.id = 1, +	.name = "wm8400-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = {  	},  	.ops = &wm8400_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8400_dai); -static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8400_suspend(struct snd_soc_codec *codec, 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) +static int wm8400_resume(struct snd_soc_codec *codec)  { -	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); - -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; +	struct snd_soc_codec *codec = priv->codec;  	/* 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) +static int wm8400_codec_probe(struct snd_soc_codec *codec)  { +	struct wm8400 *wm8400 = dev_get_platdata(codec->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;  	snd_soc_codec_set_drvdata(codec, priv); -	codec->control_data = dev_get_drvdata(&dev->dev); -	priv->wm8400 = dev_get_drvdata(&dev->dev); +	codec->control_data = priv->wm8400 = wm8400; +	priv->codec = codec; -	ret = regulator_bulk_get(priv->wm8400->dev, +	ret = regulator_bulk_get(wm8400->dev,  				 ARRAY_SIZE(power), &power[0]);  	if (ret != 0) { -		dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); +		dev_err(codec->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); @@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev)  	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;  	} - +	wm8400_add_controls(codec); +	wm8400_add_widgets(codec);  	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) +static int  wm8400_codec_remove(struct snd_soc_codec *codec)  { -	struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec); +	struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);  	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_read(codec, WM8400_POWER_MANAGEMENT_1); +	wm8400_write(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 snd_soc_codec_driver soc_codec_dev_wm8400 = { +	.probe =	wm8400_codec_probe, +	.remove =	wm8400_codec_remove, +	.suspend =	wm8400_suspend, +	.resume =	wm8400_resume, +	.read = wm8400_read, +	.write = wm8400_write, +	.set_bias_level = wm8400_set_bias_level, +}; + +static int __devinit wm8400_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400, +			&wm8400_dai, 1); +} +static int __devexit wm8400_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev);  	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), +		   .name = "wm8400-codec", +		   .owner = THIS_MODULE, +		   }, +	.probe = wm8400_probe, +	.remove = __devexit_p(wm8400_remove),  }; -static int __init wm8400_codec_init(void) +static __init int wm8400_init(void)  {  	return platform_driver_register(&wm8400_codec_driver);  } -module_init(wm8400_codec_init); +module_init(wm8400_init); -static void __exit wm8400_codec_exit(void) +static __exit void wm8400_exit(void)  {  	platform_driver_unregister(&wm8400_codec_driver);  } -module_exit(wm8400_codec_exit); - -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); +module_exit(wm8400_exit);  MODULE_DESCRIPTION("ASoC WM8400 driver");  MODULE_AUTHOR("Mark Brown"); diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h index 79c5934d4776..521adb193870 100644 --- a/sound/soc/codecs/wm8400.h +++ b/sound/soc/codecs/wm8400.h @@ -56,7 +56,4 @@  #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/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 0f7bcb61071a..d00da2001a12 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -29,10 +29,6 @@  #include "wm8510.h" -#define WM8510_VERSION "0.6" - -struct snd_soc_codec_device soc_codec_dev_wm8510; -  /*   * wm8510 register cache   * We can't read the WM8510 register space when we are @@ -61,6 +57,11 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {  #define wm8510_reset(c)	snd_soc_write(c, WM8510_RESET, 0) +/* codec private data */ +struct wm8510_priv { +	enum snd_soc_control_type control_type; +}; +  static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };  static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };  static const char *wm8510_alc[] = { "ALC", "Limiter" }; @@ -403,8 +404,7 @@ static int wm8510_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;  	u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; @@ -514,8 +514,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = {  	.set_pll	= wm8510_set_dai_pll,  }; -struct snd_soc_dai wm8510_dai = { -	.name = "WM8510 HiFi", +static struct snd_soc_dai_driver wm8510_dai = { +	.name = "wm8510-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -531,21 +531,15 @@ struct snd_soc_dai wm8510_dai = {  	.ops = &wm8510_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8510_dai); -static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8510_resume(struct platform_device *pdev) +static int wm8510_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -561,43 +555,19 @@ static int wm8510_resume(struct platform_device *pdev)  	return 0;  } -/* - * initialise the WM8510 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8510_init(struct snd_soc_device *socdev, -		       enum snd_soc_control_type control) +static int wm8510_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret = 0; - -	codec->name = "WM8510"; -	codec->owner = THIS_MODULE; -	codec->set_bias_level = wm8510_set_bias_level; -	codec->dai = &wm8510_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8510_reg); -	codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL); - -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); +	int ret; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9,  wm8510->control_type);  	if (ret < 0) { -		printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", -		       ret); -		goto err; +		printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); +		return ret;  	}  	wm8510_reset(codec); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8510: failed to create pcms\n"); -		goto err; -	} -  	/* power on device */  	codec->bias_level = SND_SOC_BIAS_OFF;  	wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -606,119 +576,52 @@ static int wm8510_init(struct snd_soc_device *socdev,  	wm8510_add_widgets(codec);  	return ret; - -err: -	kfree(codec->reg_cache); -	return ret;  } -static struct snd_soc_device *wm8510_socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8510 2 wire address is 0x1a - */ - -static int wm8510_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +/* power down chip */ +static int wm8510_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = wm8510_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret; - -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; +	struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); -	ret = wm8510_init(socdev, SND_SOC_I2C); -	if (ret < 0) -		pr_err("failed to initialise WM8510\n"); - -	return ret; -} - -static int wm8510_i2c_remove(struct i2c_client *client) -{ -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); +	kfree(wm8510);  	return 0;  } -static const struct i2c_device_id wm8510_i2c_id[] = { -	{ "wm8510", 0 }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); - -static struct i2c_driver wm8510_i2c_driver = { -	.driver = { -		.name = "WM8510 I2C Codec", -		.owner = THIS_MODULE, -	}, -	.probe =    wm8510_i2c_probe, -	.remove =   wm8510_i2c_remove, -	.id_table = wm8510_i2c_id, +static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { +	.probe =	wm8510_probe, +	.remove =	wm8510_remove, +	.suspend =	wm8510_suspend, +	.resume =	wm8510_resume, +	.set_bias_level = wm8510_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8510_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default =wm8510_reg,  }; -static int wm8510_add_i2c_device(struct platform_device *pdev, -				 const struct wm8510_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&wm8510_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "wm8510", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -			setup->i2c_bus); -		goto err_driver; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -			(unsigned int)info.addr); -		goto err_driver; -	} - -	return 0; - -err_driver: -	i2c_del_driver(&wm8510_i2c_driver); -	return -ENODEV; -} -#endif -  #if defined(CONFIG_SPI_MASTER)  static int __devinit wm8510_spi_probe(struct spi_device *spi)  { -	struct snd_soc_device *socdev = wm8510_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8510_priv *wm8510;  	int ret; -	codec->control_data = spi; +	wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); +	if (wm8510 == NULL) +		return -ENOMEM; -	ret = wm8510_init(socdev, SND_SOC_SPI); -	if (ret < 0) -		dev_err(&spi->dev, "failed to initialise WM8510\n"); +	wm8510->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8510); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8510, &wm8510_dai, 1); +	if (ret < 0) +		kfree(wm8510);  	return ret;  }  static int __devexit wm8510_spi_remove(struct spi_device *spi)  { +	snd_soc_unregister_codec(&spi->dev);  	return 0;  } @@ -733,84 +636,79 @@ static struct spi_driver wm8510_spi_driver = {  };  #endif /* CONFIG_SPI_MASTER */ -static int wm8510_probe(struct platform_device *pdev) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct wm8510_setup_data *setup; -	struct snd_soc_codec *codec; -	int ret = 0; - -	pr_info("WM8510 Audio Codec %s", WM8510_VERSION); +	struct wm8510_priv *wm8510; +	int ret; -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) +	wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); +	if (wm8510 == NULL)  		return -ENOMEM; -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); +	i2c_set_clientdata(i2c, wm8510); +	wm8510->control_type = SND_SOC_I2C; -	wm8510_socdev = socdev; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		ret = wm8510_add_i2c_device(pdev, setup); -	} -#endif -#if defined(CONFIG_SPI_MASTER) -	if (setup->spi) { -		ret = spi_register_driver(&wm8510_spi_driver); -		if (ret != 0) -			printk(KERN_ERR "can't add spi driver"); -	} -#endif - -	if (ret != 0) -		kfree(codec); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8510, &wm8510_dai, 1); +	if (ret < 0) +		kfree(wm8510);  	return ret;  } -/* power down chip */ -static int wm8510_remove(struct platform_device *pdev) +static __devexit int wm8510_i2c_remove(struct i2c_client *client)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	i2c_unregister_device(codec->control_data); -	i2c_del_driver(&wm8510_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) -	spi_unregister_driver(&wm8510_spi_driver); -#endif -	kfree(codec); - +	snd_soc_unregister_codec(&client->dev);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm8510 = { -	.probe = 	wm8510_probe, -	.remove = 	wm8510_remove, -	.suspend = 	wm8510_suspend, -	.resume =	wm8510_resume, +static const struct i2c_device_id wm8510_i2c_id[] = { +	{ "wm8510", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); + +static struct i2c_driver wm8510_i2c_driver = { +	.driver = { +		.name = "wm8510-codec", +		.owner = THIS_MODULE, +	}, +	.probe =    wm8510_i2c_probe, +	.remove =   __devexit_p(wm8510_i2c_remove), +	.id_table = wm8510_i2c_id,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); +#endif  static int __init wm8510_modinit(void)  { -	return snd_soc_register_dai(&wm8510_dai); +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8510_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", +		       ret); +	} +#endif +#if defined(CONFIG_SPI_MASTER) +	ret = spi_register_driver(&wm8510_spi_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n", +		       ret); +	} +#endif +	return ret;  }  module_init(wm8510_modinit);  static void __exit wm8510_exit(void)  { -	snd_soc_unregister_dai(&wm8510_dai); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	i2c_del_driver(&wm8510_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) +	spi_unregister_driver(&wm8510_spi_driver); +#endif  }  module_exit(wm8510_exit); diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h index bdefcf5c69ff..b3e26ed9f2d0 100644 --- a/sound/soc/codecs/wm8510.h +++ b/sound/soc/codecs/wm8510.h @@ -99,7 +99,4 @@ struct wm8510_setup_data {  	unsigned short i2c_address;  }; -extern struct snd_soc_dai wm8510_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8510; -  #endif diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 0ad039b4adf5..712ef7c76f90 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -30,9 +30,6 @@  #include "wm8523.h" -static struct snd_soc_codec *wm8523_codec; -struct snd_soc_codec_device soc_codec_dev_wm8523; -  #define WM8523_NUM_SUPPLIES 2  static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {  	"AVDD", @@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {  /* codec private data */  struct wm8523_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	u16 reg_cache[WM8523_REGISTER_COUNT];  	struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];  	unsigned int sysclk; @@ -162,8 +159,7 @@ static int wm8523_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);  	int i;  	u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); @@ -387,8 +383,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = {  	.set_fmt	= wm8523_set_dai_fmt,  }; -struct snd_soc_dai wm8523_dai = { -	.name = "WM8523", +static struct snd_soc_dai_driver wm8523_dai = { +	.name = "wm8523-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2,  /* Mono modes not yet supported */ @@ -398,25 +394,17 @@ struct snd_soc_dai wm8523_dai = {  	},  	.ops = &wm8523_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8523_dai);  #ifdef CONFIG_PM -static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8523_resume(struct platform_device *pdev) +static int wm8523_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -  	return 0;  }  #else @@ -424,93 +412,20 @@ static int wm8523_resume(struct platform_device *pdev)  #define wm8523_resume NULL  #endif -static int wm8523_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8523_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8523_codec; -	codec = wm8523_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8523_snd_controls, -			     ARRAY_SIZE(wm8523_snd_controls)); -	wm8523_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -static int wm8523_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_wm8523 = { -	.probe = 	wm8523_probe, -	.remove = 	wm8523_remove, -	.suspend = 	wm8523_suspend, -	.resume =	wm8523_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); - -static int wm8523_register(struct wm8523_priv *wm8523, -			   enum snd_soc_control_type control) +static int wm8523_probe(struct snd_soc_codec *codec)  { -	int ret; -	struct snd_soc_codec *codec = &wm8523->codec; -	int i; - -	if (wm8523_codec) { -		dev_err(codec->dev, "Another WM8523 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8523); -	codec->name = "WM8523"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8523_set_bias_level; -	codec->dai = &wm8523_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8523_REGISTER_COUNT; -	codec->reg_cache = &wm8523->reg_cache; -	codec->volatile_register = wm8523_volatile_register; +	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); +	int ret, i; +	codec->hw_write = (hw_write_t)i2c_master_send;  	wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];  	wm8523->rate_constraint.count =  		ARRAY_SIZE(wm8523->rate_constraint_list); -	memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) @@ -520,7 +435,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,  				 wm8523->supplies);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; +		return ret;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), @@ -555,8 +470,6 @@ static int wm8523_register(struct wm8523_priv *wm8523,  		goto err_enable;  	} -	wm8523_dai.dev = codec->dev; -  	/* Change some default settings - latch VU and enable ZC */  	wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;  	wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; @@ -566,69 +479,67 @@ static int wm8523_register(struct wm8523_priv *wm8523,  	/* Bias level configuration will have done an extra enable */  	regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -	wm8523_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_enable; -	} - -	ret = snd_soc_register_dai(&wm8523_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8523_snd_controls, +			     ARRAY_SIZE(wm8523_snd_controls)); +	wm8523_add_widgets(codec);  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);  err_get:  	regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err: -	kfree(wm8523); +  	return ret;  } -static void wm8523_unregister(struct wm8523_priv *wm8523) +static int wm8523_remove(struct snd_soc_codec *codec)  { -	wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); +	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + +	wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);  	regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -	snd_soc_unregister_dai(&wm8523_dai); -	snd_soc_unregister_codec(&wm8523->codec); -	kfree(wm8523); -	wm8523_codec = NULL; +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { +	.probe =	wm8523_probe, +	.remove =	wm8523_remove, +	.suspend =	wm8523_suspend, +	.resume =	wm8523_resume, +	.set_bias_level = wm8523_set_bias_level, +	.reg_cache_size = WM8523_REGISTER_COUNT, +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8523_reg, +	.volatile_register = wm8523_volatile_register, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8523_priv *wm8523; -	struct snd_soc_codec *codec; +	int ret;  	wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);  	if (wm8523 == NULL)  		return -ENOMEM; -	codec = &wm8523->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, wm8523); -	codec->control_data = i2c; +	wm8523->control_type = SND_SOC_I2C; -	codec->dev = &i2c->dev; +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8523, &wm8523_dai, 1); +	if (ret < 0) +		kfree(wm8523); +	return ret; -	return wm8523_register(wm8523, SND_SOC_I2C);  }  static __devexit int wm8523_i2c_remove(struct i2c_client *client)  { -	struct wm8523_priv *wm8523 = i2c_get_clientdata(client); -	wm8523_unregister(wm8523); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -640,7 +551,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);  static struct i2c_driver wm8523_i2c_driver = {  	.driver = { -		.name = "WM8523", +		.name = "wm8523-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8523_i2c_probe, diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h index 1aa9ce3e1357..4d5b1eb8f2fc 100644 --- a/sound/soc/codecs/wm8523.h +++ b/sound/soc/codecs/wm8523.h @@ -154,7 +154,4 @@  #define WM8523_ZD_COUNT_SHIFT                        0  /* ZD_COUNT - [1:0] */  #define WM8523_ZD_COUNT_WIDTH                        2  /* ZD_COUNT - [1:0] */ -extern struct snd_soc_dai wm8523_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8523; -  #endif diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 1881b16bc248..b1a80e5ff8b5 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -199,7 +199,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {  /* codec private data */  struct wm8580_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];  	u16 reg_cache[WM8580_MAX_REGISTER + 1];  	struct pll_state a; @@ -484,9 +484,8 @@ static int wm8580_paif_hw_params(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; -	u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); +	struct snd_soc_codec *codec = rtd->codec; +	u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id);  	paifb &= ~WM8580_AIF_LENGTH_MASK;  	/* bit size */ @@ -506,7 +505,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); +	snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb);  	return 0;  } @@ -518,8 +517,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,  	unsigned int aifb;  	int can_invert_lrclk; -	aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); -	aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); +	aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); +	aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id);  	aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); @@ -585,8 +584,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); -	snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); +	snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); +	snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb);  	return 0;  } @@ -746,10 +745,10 @@ static struct snd_soc_dai_ops wm8580_dai_ops_capture = {  	.set_pll	= wm8580_set_dai_pll,  }; -struct snd_soc_dai wm8580_dai[] = { +static struct snd_soc_dai_driver wm8580_dai[] = {  	{ -		.name = "WM8580 PAIFRX", -		.id = 0, +		.name = "wm8580-hifi-playback", +		.id	= WM8580_DAI_PAIFRX,  		.playback = {  			.stream_name = "Playback",  			.channels_min = 1, @@ -760,8 +759,8 @@ struct snd_soc_dai wm8580_dai[] = {  		.ops = &wm8580_dai_ops_playback,  	},  	{ -		.name = "WM8580 PAIFTX", -		.id = 1, +		.name = "wm8580-hifi-capture", +		.id	=	WM8580_DAI_PAIFTX,  		.capture = {  			.stream_name = "Capture",  			.channels_min = 2, @@ -772,90 +771,16 @@ struct snd_soc_dai wm8580_dai[] = {  		.ops = &wm8580_dai_ops_capture,  	},  }; -EXPORT_SYMBOL_GPL(wm8580_dai); -static struct snd_soc_codec *wm8580_codec; - -static int wm8580_probe(struct platform_device *pdev) +static int wm8580_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8580_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8580_codec; -	codec = wm8580_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8580_snd_controls, -			     ARRAY_SIZE(wm8580_snd_controls)); -	wm8580_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -/* power down chip */ -static int wm8580_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_wm8580 = { -	.probe = 	wm8580_probe, -	.remove = 	wm8580_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); - -static int wm8580_register(struct wm8580_priv *wm8580, -			   enum snd_soc_control_type control) -{ -	int ret, i; -	struct snd_soc_codec *codec = &wm8580->codec; - -	if (wm8580_codec) { -		dev_err(codec->dev, "Another WM8580 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8580); -	codec->name = "WM8580"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8580_set_bias_level; -	codec->dai = wm8580_dai; -	codec->num_dai = ARRAY_SIZE(wm8580_dai); -	codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); -	codec->reg_cache = &wm8580->reg_cache; - -	memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); +	struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); +	int ret = 0,i; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) @@ -865,7 +790,7 @@ static int wm8580_register(struct wm8580_priv *wm8580,  				 wm8580->supplies);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; +		return ret;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), @@ -882,74 +807,68 @@ static int wm8580_register(struct wm8580_priv *wm8580,  		goto err_regulator_enable;  	} -	for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) -		wm8580_dai[i].dev = codec->dev; -  	wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	wm8580_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_regulator_enable; -	} - -	ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8580_snd_controls, +			     ARRAY_SIZE(wm8580_snd_controls)); +	wm8580_add_widgets(codec);  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_regulator_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);  err_regulator_get:  	regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -err: -	kfree(wm8580);  	return ret;  } -static void wm8580_unregister(struct wm8580_priv *wm8580) +/* power down chip */ +static int wm8580_remove(struct snd_soc_codec *codec)  { -	wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); -	snd_soc_unregister_codec(&wm8580->codec); +	struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); + +	wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); +  	regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);  	regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -	kfree(wm8580); -	wm8580_codec = NULL; + +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { +	.probe =	wm8580_probe, +	.remove =	wm8580_remove, +	.set_bias_level = wm8580_set_bias_level, +	.reg_cache_size = sizeof(wm8580_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = &wm8580_reg, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static int wm8580_i2c_probe(struct i2c_client *i2c,  			    const struct i2c_device_id *id)  {  	struct wm8580_priv *wm8580; -	struct snd_soc_codec *codec; +	int ret;  	wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);  	if (wm8580 == NULL)  		return -ENOMEM; -	codec = &wm8580->codec; -  	i2c_set_clientdata(i2c, wm8580); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm8580->control_type = SND_SOC_I2C; -	return wm8580_register(wm8580, SND_SOC_I2C); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); +	if (ret < 0) +		kfree(wm8580); +	return ret;  }  static int wm8580_i2c_remove(struct i2c_client *client)  { -	struct wm8580_priv *wm8580 = i2c_get_clientdata(client); -	wm8580_unregister(wm8580); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -961,7 +880,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);  static struct i2c_driver wm8580_i2c_driver = {  	.driver = { -		.name = "wm8580", +		.name = "wm8580-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8580_i2c_probe, @@ -972,7 +891,7 @@ static struct i2c_driver wm8580_i2c_driver = {  static int __init wm8580_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8580_i2c_driver); @@ -981,7 +900,7 @@ static int __init wm8580_modinit(void)  	}  #endif -	return 0; +	return ret;  }  module_init(wm8580_modinit); diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 0dfb5ddde6a2..8328ef667593 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h @@ -31,8 +31,5 @@  #define WM8580_DAI_PAIFRX 0  #define WM8580_DAI_PAIFTX 1 -extern struct snd_soc_dai wm8580_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8580; -  #endif diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index e2dba07f0260..f8d9c60e7fad 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -31,11 +31,9 @@  #include "wm8711.h" -static struct snd_soc_codec *wm8711_codec; -  /* codec private data */  struct wm8711_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type bus_type;  	u16 reg_cache[WM8711_CACHEREGNUM];  	unsigned int sysclk;  }; @@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_dai *dai)  {  	struct snd_soc_codec *codec = dai->codec; -	struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); +	struct wm8711_priv *wm8711 =  snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;  	int i = get_coeff(wm8711->sysclk, params_rate(params));  	u16 srate = (coeff_div[i].sr << 2) | @@ -227,7 +225,7 @@ static int wm8711_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 wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); +	struct wm8711_priv *wm8711 =  snd_soc_codec_get_drvdata(codec);  	switch (freq) {  	case 11289600: @@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = {  	.set_fmt = wm8711_set_dai_fmt,  }; -struct snd_soc_dai wm8711_dai = { -	.name = "WM8711", +static struct snd_soc_dai_driver wm8711_dai = { +	.name = "wm8711-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = {  	},  	.ops = &wm8711_ops,  }; -EXPORT_SYMBOL_GPL(wm8711_dai); -static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	snd_soc_write(codec, WM8711_ACTIVE, 0x0);  	wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8711_resume(struct platform_device *pdev) +static int wm8711_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev)  	return 0;  } -static int wm8711_probe(struct platform_device *pdev) +static int wm8711_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8711_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8711_codec; -	codec = wm8711_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8711_snd_controls, -			     ARRAY_SIZE(wm8711_snd_controls)); -	wm8711_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -/* power down chip */ -static int wm8711_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_wm8711 = { -	.probe = 	wm8711_probe, -	.remove = 	wm8711_remove, -	.suspend = 	wm8711_suspend, -	.resume =	wm8711_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); - -static int wm8711_register(struct wm8711_priv *wm8711, -			   enum snd_soc_control_type control) -{ -	int ret; -	struct snd_soc_codec *codec = &wm8711->codec; -	u16 reg; - -	if (wm8711_codec) { -		dev_err(codec->dev, "Another WM8711 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8711); -	codec->name = "WM8711"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8711_set_bias_level; -	codec->dai = &wm8711_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8711_CACHEREGNUM; -	codec->reg_cache = &wm8711->reg_cache; - -	memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); +	struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); +	int ret, reg; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	ret = wm8711_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		return ret;  	} -	wm8711_dai.dev = codec->dev; -  	wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	/* Latch the update bits */ @@ -481,69 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711,  	reg = snd_soc_read(codec, WM8711_ROUT1V);  	snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); -	wm8711_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm8711_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; +	snd_soc_add_controls(codec, wm8711_snd_controls, +			     ARRAY_SIZE(wm8711_snd_controls)); +	wm8711_add_widgets(codec); -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8711);  	return ret; +  } -static void wm8711_unregister(struct wm8711_priv *wm8711) +/* power down chip */ +static int wm8711_remove(struct snd_soc_codec *codec)  { -	wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8711_dai); -	snd_soc_unregister_codec(&wm8711->codec); -	kfree(wm8711); -	wm8711_codec = NULL; +	wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { +	.probe =	wm8711_probe, +	.remove =	wm8711_remove, +	.suspend =	wm8711_suspend, +	.resume =	wm8711_resume, +	.set_bias_level = wm8711_set_bias_level, +	.reg_cache_size = sizeof(wm8711_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8711_reg, +}; +  #if defined(CONFIG_SPI_MASTER)  static int __devinit wm8711_spi_probe(struct spi_device *spi)  { -	struct snd_soc_codec *codec;  	struct wm8711_priv *wm8711; +	int ret;  	wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);  	if (wm8711 == NULL)  		return -ENOMEM; -	codec = &wm8711->codec; -	codec->control_data = spi; -	codec->dev = &spi->dev; +	spi_set_drvdata(spi, wm8711); +	wm8711->bus_type = SND_SOC_SPI; -	dev_set_drvdata(&spi->dev, wm8711); - -	return wm8711_register(wm8711, SND_SOC_SPI); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8711, &wm8711_dai, 1); +	if (ret < 0) +		kfree(wm8711); +	return ret;  }  static int __devexit wm8711_spi_remove(struct spi_device *spi)  { -	struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); - -	wm8711_unregister(wm8711); - +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver wm8711_spi_driver = {  	.driver = { -		.name	= "wm8711", +		.name	= "wm8711-codec",  		.bus	= &spi_bus_type,  		.owner	= THIS_MODULE,  	}, @@ -553,31 +462,30 @@ static struct spi_driver wm8711_spi_driver = {  #endif /* CONFIG_SPI_MASTER */  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, +static __devinit int wm8711_i2c_probe(struct i2c_client *client,  				      const struct i2c_device_id *id)  {  	struct wm8711_priv *wm8711; -	struct snd_soc_codec *codec; +	int ret;  	wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);  	if (wm8711 == NULL)  		return -ENOMEM; -	codec = &wm8711->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; - -	i2c_set_clientdata(i2c, wm8711); -	codec->control_data = i2c; +	i2c_set_clientdata(client, wm8711); +	wm8711->bus_type = SND_SOC_I2C; -	codec->dev = &i2c->dev; - -	return wm8711_register(wm8711, SND_SOC_I2C); +	ret =  snd_soc_register_codec(&client->dev, +			&soc_codec_dev_wm8711, &wm8711_dai, 1); +	if (ret < 0) +		kfree(wm8711); +	return ret;  }  static __devexit int wm8711_i2c_remove(struct i2c_client *client)  { -	struct wm8711_priv *wm8711 = i2c_get_clientdata(client); -	wm8711_unregister(wm8711); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -589,7 +497,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);  static struct i2c_driver wm8711_i2c_driver = {  	.driver = { -		.name = "WM8711 I2C Codec", +		.name = "wm8711-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8711_i2c_probe, diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h index 381e84a43816..a61db985499f 100644 --- a/sound/soc/codecs/wm8711.h +++ b/sound/soc/codecs/wm8711.h @@ -36,7 +36,4 @@ struct wm8711_setup_data {  	unsigned short i2c_address;  }; -extern struct snd_soc_dai wm8711_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8711; -  #endif diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 9d1df2628136..6a40080ba701 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -23,7 +23,6 @@  #include <sound/initval.h>  #include <sound/soc.h> -#include "wm8727.h"  /*   * Note this is a simple chip with no configuration interface, sample rate is   * determined automatically by examining the Master clock and Bit clock ratios @@ -33,8 +32,8 @@  			SNDRV_PCM_RATE_192000) -struct snd_soc_dai wm8727_dai = { -	.name = "WM8727", +static struct snd_soc_dai_driver wm8727_dai = { +	.name = "wm8727-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = {  		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,  		},  }; -EXPORT_SYMBOL_GPL(wm8727_dai); -static struct snd_soc_codec *wm8727_codec; +struct snd_soc_codec_driver soc_codec_dev_wm8727; -static int wm8727_soc_probe(struct platform_device *pdev) +static __devinit int wm8727_probe(struct platform_device *pdev)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	int ret = 0; - -	BUG_ON(!wm8727_codec); - -	socdev->card->codec = wm8727_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8727: failed to create pcms\n"); -		goto pcm_err; -	} - -	return ret; - -pcm_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL; -	return ret; -} - -static int wm8727_soc_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_dev_wm8727 = { -	.probe = 	wm8727_soc_probe, -	.remove = 	wm8727_soc_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727); - - -static __devinit int wm8727_platform_probe(struct platform_device *pdev) -{ -	struct snd_soc_codec *codec; -	int ret; - -	if (wm8727_codec) { -		dev_err(&pdev->dev, "Another WM8727 is registered\n"); -		return -EBUSY; -	} - -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; -	wm8727_codec = codec; - -	platform_set_drvdata(pdev, codec); - -	mutex_init(&codec->mutex); -	codec->dev = &pdev->dev; -	codec->name = "WM8727"; -	codec->owner = THIS_MODULE; -	codec->dai = &wm8727_dai; -	codec->num_dai = 1; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	wm8727_dai.dev = &pdev->dev; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm8727_dai); -	if (ret != 0) { -		dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(codec); -	return ret; +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_wm8727, &wm8727_dai, 1);  } -static int __devexit wm8727_platform_remove(struct platform_device *pdev) +static int __devexit wm8727_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&wm8727_dai); -	snd_soc_unregister_codec(platform_get_drvdata(pdev)); +	snd_soc_unregister_codec(&pdev->dev);  	return 0;  } @@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = {  			.owner = THIS_MODULE,  	}, -	.probe = wm8727_platform_probe, -	.remove = __devexit_p(wm8727_platform_remove), +	.probe = wm8727_probe, +	.remove = __devexit_p(wm8727_remove),  };  static int __init wm8727_init(void) diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h deleted file mode 100644 index ee19aa71bcdc..000000000000 --- a/sound/soc/codecs/wm8727.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * wm8727.h - * - *  Created on: 15-Oct-2009 - *      Author: neil.jones@imgtec.com - * - * Copyright (C) 2009 Imagination Technologies Ltd. - * - *  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 WM8727_H_ -#define WM8727_H_ - -extern struct snd_soc_dai wm8727_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8727; - -#endif /* WM8727_H_ */ diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 34be2d2b69ef..5e5a1625194c 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -29,8 +29,6 @@  #include "wm8728.h" -struct snd_soc_codec_device soc_codec_dev_wm8728; -  /*   * We can't read the WM8728 register space so we cache them instead.   * Note that the defaults here aren't the physical defaults, we latch @@ -44,6 +42,11 @@ static const u16 wm8728_reg_defaults[] = {  	0x100,  }; +/* codec private data */ +struct wm8728_priv { +	enum snd_soc_control_type control_type; +}; +  static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);  static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -96,8 +99,7 @@ static int wm8728_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 dac = snd_soc_read(codec, WM8728_DACCTL);  	dac &= ~0x18; @@ -210,8 +212,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = {  	.set_fmt	= wm8728_set_dai_fmt,  }; -struct snd_soc_dai wm8728_dai = { -	.name = "WM8728", +static struct snd_soc_dai_driver wm8728_dai = { +	.name = "wm8728-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -221,63 +223,31 @@ struct snd_soc_dai wm8728_dai = {  	},  	.ops = &wm8728_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8728_dai); -static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8728_resume(struct platform_device *pdev) +static int wm8728_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -/* - * initialise the WM8728 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8728_init(struct snd_soc_device *socdev, -		       enum snd_soc_control_type control) +static int wm8728_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret = 0; - -	codec->name = "WM8728"; -	codec->owner = THIS_MODULE; -	codec->set_bias_level = wm8728_set_bias_level; -	codec->dai = &wm8728_dai; -	codec->num_dai = 1; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); -	codec->reg_cache = kmemdup(wm8728_reg_defaults, -				   sizeof(wm8728_reg_defaults), -				   GFP_KERNEL); -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); +	int ret; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type);  	if (ret < 0) {  		printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",  		       ret); -		goto err; -	} - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8728: failed to create pcms\n"); -		goto err; +		return ret;  	}  	/* power on device */ @@ -288,128 +258,55 @@ static int wm8728_init(struct snd_soc_device *socdev,  	wm8728_add_widgets(codec);  	return ret; - -err: -	kfree(codec->reg_cache); -	return ret;  } -static struct snd_soc_device *wm8728_socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8728 2 wire address is determined by GPIO5 - * state during powerup. - *    low  = 0x1a - *    high = 0x1b - */ - -static int wm8728_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static int wm8728_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = wm8728_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; -	int ret; - -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; - -	ret = wm8728_init(socdev, SND_SOC_I2C); -	if (ret < 0) -		pr_err("failed to initialise WM8728\n"); - -	return ret; -} - -static int wm8728_i2c_remove(struct i2c_client *client) -{ -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static const struct i2c_device_id wm8728_i2c_id[] = { -	{ "wm8728", 0 }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); - -static struct i2c_driver wm8728_i2c_driver = { -	.driver = { -		.name = "WM8728 I2C Codec", -		.owner = THIS_MODULE, -	}, -	.probe =    wm8728_i2c_probe, -	.remove =   wm8728_i2c_remove, -	.id_table = wm8728_i2c_id, +static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { +	.probe =	wm8728_probe, +	.remove =	wm8728_remove, +	.suspend =	wm8728_suspend, +	.resume =	wm8728_resume, +	.set_bias_level = wm8728_set_bias_level, +	.reg_cache_size = sizeof(wm8728_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8728_reg_defaults,  }; -static int wm8728_add_i2c_device(struct platform_device *pdev, -				 const struct wm8728_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&wm8728_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "wm8728", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -			setup->i2c_bus); -		goto err_driver; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -			(unsigned int)info.addr); -		goto err_driver; -	} - -	return 0; - -err_driver: -	i2c_del_driver(&wm8728_i2c_driver); -	return -ENODEV; -} -#endif -  #if defined(CONFIG_SPI_MASTER)  static int __devinit wm8728_spi_probe(struct spi_device *spi)  { -	struct snd_soc_device *socdev = wm8728_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8728_priv *wm8728;  	int ret; -	codec->control_data = spi; +	wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); +	if (wm8728 == NULL) +		return -ENOMEM; -	ret = wm8728_init(socdev, SND_SOC_SPI); -	if (ret < 0) -		dev_err(&spi->dev, "failed to initialise WM8728\n"); +	wm8728->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8728); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8728, &wm8728_dai, 1); +	if (ret < 0) +		kfree(wm8728);  	return ret;  }  static int __devexit wm8728_spi_remove(struct spi_device *spi)  { +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver wm8728_spi_driver = {  	.driver = { -		.name	= "wm8728", +		.name	= "wm8728-codec",  		.bus	= &spi_bus_type,  		.owner	= THIS_MODULE,  	}, @@ -418,85 +315,80 @@ static struct spi_driver wm8728_spi_driver = {  };  #endif /* CONFIG_SPI_MASTER */ -static int wm8728_probe(struct platform_device *pdev) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct wm8728_setup_data *setup; -	struct snd_soc_codec *codec; -	int ret = 0; +	struct wm8728_priv *wm8728; +	int ret; -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) +	wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); +	if (wm8728 == NULL)  		return -ENOMEM; -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); +	i2c_set_clientdata(i2c, wm8728); +	wm8728->control_type = SND_SOC_I2C; + +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8728, &wm8728_dai, 1); +	if (ret < 0) +		kfree(wm8728); +	return ret; +} + +static __devexit int wm8728_i2c_remove(struct i2c_client *client) +{ +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client)); +	return 0; +} -	wm8728_socdev = socdev; -	ret = -ENODEV; +static const struct i2c_device_id wm8728_i2c_id[] = { +	{ "wm8728", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); + +static struct i2c_driver wm8728_i2c_driver = { +	.driver = { +		.name = "wm8728-codec", +		.owner = THIS_MODULE, +	}, +	.probe =    wm8728_i2c_probe, +	.remove =   __devexit_p(wm8728_i2c_remove), +	.id_table = wm8728_i2c_id, +}; +#endif +static int __init wm8728_modinit(void) +{ +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		ret = wm8728_add_i2c_device(pdev, setup); +	ret = i2c_add_driver(&wm8728_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", +		       ret);  	}  #endif  #if defined(CONFIG_SPI_MASTER) -	if (setup->spi) { -		ret = spi_register_driver(&wm8728_spi_driver); -		if (ret != 0) -			printk(KERN_ERR "can't add spi driver"); +	ret = spi_register_driver(&wm8728_spi_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", +		       ret);  	}  #endif - -	if (ret != 0) -		kfree(codec); -  	return ret;  } +module_init(wm8728_modinit); -/* power down chip */ -static int wm8728_remove(struct platform_device *pdev) +static void __exit wm8728_exit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev);  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	i2c_unregister_device(codec->control_data);  	i2c_del_driver(&wm8728_i2c_driver);  #endif  #if defined(CONFIG_SPI_MASTER)  	spi_unregister_driver(&wm8728_spi_driver);  #endif -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8728 = { -	.probe = 	wm8728_probe, -	.remove = 	wm8728_remove, -	.suspend = 	wm8728_suspend, -	.resume =	wm8728_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); - -static int __init wm8728_modinit(void) -{ -	return snd_soc_register_dai(&wm8728_dai); -} -module_init(wm8728_modinit); - -static void __exit wm8728_exit(void) -{ -	snd_soc_unregister_dai(&wm8728_dai);  }  module_exit(wm8728_exit); diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h index d269c132474b..8aea362ffd47 100644 --- a/sound/soc/codecs/wm8728.h +++ b/sound/soc/codecs/wm8728.h @@ -18,13 +18,4 @@  #define WM8728_DACCTL    0x02  #define WM8728_IFCTL     0x03 -struct wm8728_setup_data { -	int            spi; -	int            i2c_bus; -	unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8728_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8728; -  #endif diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0ab9b6355297..19844fc8cb1d 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -32,9 +32,6 @@  #include "wm8731.h" -static struct snd_soc_codec *wm8731_codec; -struct snd_soc_codec_device soc_codec_dev_wm8731; -  #define WM8731_NUM_SUPPLIES 4  static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {  	"AVDD", @@ -45,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {  /* codec private data */  struct wm8731_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];  	u16 reg_cache[WM8731_CACHEREGNUM];  	unsigned int sysclk; @@ -222,9 +219,7 @@ static int wm8731_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; +	struct snd_soc_codec *codec = dai->codec;  	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;  	int i = get_coeff(wm8731->sysclk, params_rate(params)); @@ -252,9 +247,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,  static int wm8731_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; +	struct snd_soc_codec *codec = dai->codec;  	/* set active */  	snd_soc_write(codec, WM8731_ACTIVE, 0x0001); @@ -265,9 +258,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,  static void wm8731_shutdown(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; +	struct snd_soc_codec *codec = dai->codec;  	/* deactivate */  	if (!codec->active) { @@ -428,8 +419,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = {  	.set_fmt	= wm8731_set_dai_fmt,  }; -struct snd_soc_dai wm8731_dai = { -	.name = "WM8731", +static struct snd_soc_dai_driver wm8731_dai = { +	.name = "wm8731-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -445,24 +436,17 @@ struct snd_soc_dai wm8731_dai = {  	.ops = &wm8731_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8731_dai);  #ifdef CONFIG_PM -static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8731_resume(struct platform_device *pdev) +static int wm8731_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -472,88 +456,17 @@ static int wm8731_resume(struct platform_device *pdev)  #define wm8731_resume NULL  #endif -static int wm8731_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8731_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8731_codec; -	codec = wm8731_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8731_snd_controls, -			     ARRAY_SIZE(wm8731_snd_controls)); -	wm8731_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -/* power down chip */ -static int wm8731_remove(struct platform_device *pdev) +static int wm8731_probe(struct snd_soc_codec *codec)  { -	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_wm8731 = { -	.probe = 	wm8731_probe, -	.remove = 	wm8731_remove, -	.suspend = 	wm8731_suspend, -	.resume =	wm8731_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); - -static int wm8731_register(struct wm8731_priv *wm8731, -			   enum snd_soc_control_type control) -{ -	int ret, i; -	struct snd_soc_codec *codec = &wm8731->codec; - -	if (wm8731_codec) { -		dev_err(codec->dev, "Another WM8731 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8731); -	codec->name = "WM8731"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8731_set_bias_level; -	codec->dai = &wm8731_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8731_CACHEREGNUM; -	codec->reg_cache = &wm8731->reg_cache; +	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); +	int ret = 0, i; -	memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); +	codec->bias_level = SND_SOC_BIAS_OFF, -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) @@ -563,7 +476,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,  				 wm8731->supplies);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; +		return ret;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), @@ -579,8 +492,6 @@ static int wm8731_register(struct wm8731_priv *wm8731,  		goto err_regulator_enable;  	} -	wm8731_dai.dev = codec->dev; -  	wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	/* Latch the update bits */ @@ -592,78 +503,78 @@ static int wm8731_register(struct wm8731_priv *wm8731,  	/* Disable bypass path by default */  	snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); -	wm8731_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_regulator_enable; -	} - -	ret = snd_soc_register_dai(&wm8731_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8731_snd_controls, +			     ARRAY_SIZE(wm8731_snd_controls)); +	wm8731_add_widgets(codec);  	/* Regulators will have been enabled by bias management */  	regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_regulator_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);  err_regulator_get:  	regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); -err: +  	kfree(wm8731);  	return ret;  } -static void wm8731_unregister(struct wm8731_priv *wm8731) +/* power down chip */ +static int wm8731_remove(struct snd_soc_codec *codec)  { -	wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8731_dai); -	snd_soc_unregister_codec(&wm8731->codec); +	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + +	wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); + +	regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);  	regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); -	kfree(wm8731); -	wm8731_codec = NULL; + +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { +	.probe =	wm8731_probe, +	.remove =	wm8731_remove, +	.suspend =	wm8731_suspend, +	.resume =	wm8731_resume, +	.set_bias_level = wm8731_set_bias_level, +	.reg_cache_size = sizeof(wm8731_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8731_reg, +}; +  #if defined(CONFIG_SPI_MASTER)  static int __devinit wm8731_spi_probe(struct spi_device *spi)  { -	struct snd_soc_codec *codec;  	struct wm8731_priv *wm8731; +	int ret;  	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);  	if (wm8731 == NULL)  		return -ENOMEM; -	codec = &wm8731->codec; -	codec->control_data = spi; -	codec->dev = &spi->dev; - -	dev_set_drvdata(&spi->dev, wm8731); +	wm8731->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8731); -	return wm8731_register(wm8731, SND_SOC_SPI); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8731, &wm8731_dai, 1); +	if (ret < 0) +		kfree(wm8731); +	return ret;  }  static int __devexit wm8731_spi_remove(struct spi_device *spi)  { -	struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev); - -	wm8731_unregister(wm8731); - +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver wm8731_spi_driver = {  	.driver = { -		.name	= "wm8731", +		.name	= "wm8731-codec",  		.bus	= &spi_bus_type,  		.owner	= THIS_MODULE,  	}, @@ -677,26 +588,26 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8731_priv *wm8731; -	struct snd_soc_codec *codec; +	int ret;  	wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);  	if (wm8731 == NULL)  		return -ENOMEM; -	codec = &wm8731->codec; -  	i2c_set_clientdata(i2c, wm8731); -	codec->control_data = i2c; +	wm8731->control_type = SND_SOC_I2C; -	codec->dev = &i2c->dev; - -	return wm8731_register(wm8731, SND_SOC_I2C); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8731, &wm8731_dai, 1); +	if (ret < 0) +		kfree(wm8731); +	return ret;  }  static __devexit int wm8731_i2c_remove(struct i2c_client *client)  { -	struct wm8731_priv *wm8731 = i2c_get_clientdata(client); -	wm8731_unregister(wm8731); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -708,7 +619,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);  static struct i2c_driver wm8731_i2c_driver = {  	.driver = { -		.name = "wm8731", +		.name = "wm8731-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8731_i2c_probe, @@ -719,7 +630,7 @@ static struct i2c_driver wm8731_i2c_driver = {  static int __init wm8731_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8731_i2c_driver);  	if (ret != 0) { @@ -734,7 +645,7 @@ static int __init wm8731_modinit(void)  		       ret);  	}  #endif -	return 0; +	return ret;  }  module_init(wm8731_modinit); diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index cd7b806e8ad0..73a70e206ba9 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h @@ -34,7 +34,4 @@  #define WM8731_SYSCLK	0  #define WM8731_DAI		0 -extern struct snd_soc_dai wm8731_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8731; -  #endif diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b9ea8904ad4b..782fe539662b 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -30,9 +30,6 @@  #include "wm8741.h" -static struct snd_soc_codec *wm8741_codec; -struct snd_soc_codec_device soc_codec_dev_wm8741; -  #define WM8741_NUM_SUPPLIES 2  static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {  	"AVDD", @@ -43,7 +40,7 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {  /* codec private data */  struct wm8741_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	u16 reg_cache[WM8741_REGISTER_COUNT];  	struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];  	unsigned int sysclk; @@ -145,8 +142,7 @@ static int wm8741_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;  	int i; @@ -314,7 +310,7 @@ static struct snd_soc_dai_ops wm8741_dai_ops = {  	.set_fmt	= wm8741_set_dai_fmt,  }; -struct snd_soc_dai wm8741_dai = { +static struct snd_soc_dai_driver wm8741_dai = {  	.name = "WM8741",  	.playback = {  		.stream_name = "Playback", @@ -325,13 +321,10 @@ struct snd_soc_dai wm8741_dai = {  	},  	.ops = &wm8741_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8741_dai);  #ifdef CONFIG_PM -static int wm8741_resume(struct platform_device *pdev) +static int wm8741_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	u16 *cache = codec->reg_cache;  	int i; @@ -348,189 +341,103 @@ static int wm8741_resume(struct platform_device *pdev)  #define wm8741_resume NULL  #endif -static int wm8741_probe(struct platform_device *pdev) +static int wm8741_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; -	if (wm8741_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm8741_codec; -	codec = wm8741_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = wm8741_reset(codec);  	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto pcm_err; +		dev_err(codec->dev, "Failed to issue reset\n"); +		return ret;  	} +	/* Change some default settings - latch VU */ +	wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; +	wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; +	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; +	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; +  	snd_soc_add_controls(codec, wm8741_snd_controls,  			     ARRAY_SIZE(wm8741_snd_controls));  	wm8741_add_widgets(codec); +	dev_dbg(codec->dev, "Successful registration\n");  	return ret; - -pcm_err: -	return ret; -} - -static int wm8741_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_wm8741 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {  	.probe =	wm8741_probe, -	.remove =	wm8741_remove,  	.resume =	wm8741_resume, +	.reg_cache_size = sizeof(wm8741_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = &wm8741_reg_defaults,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741); -static int wm8741_register(struct wm8741_priv *wm8741, -			   enum snd_soc_control_type control) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static int wm8741_i2c_probe(struct i2c_client *i2c, +			    const struct i2c_device_id *id)  { -	int ret; -	struct snd_soc_codec *codec = &wm8741->codec; -	int i; - -	if (wm8741_codec) { -		dev_err(codec->dev, "Another WM8741 is registered\n"); -		return -EINVAL; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); +	struct wm8741_priv *wm8741; +	int ret, i; -	snd_soc_codec_set_drvdata(codec, wm8741); -	codec->name = "WM8741"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = NULL; -	codec->dai = &wm8741_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8741_REGISTER_COUNT; -	codec->reg_cache = &wm8741->reg_cache; +	wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); +	if (wm8741 == NULL) +		return -ENOMEM;  	wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0];  	wm8741->rate_constraint.count =  		ARRAY_SIZE(wm8741->rate_constraint_list); -	memcpy(codec->reg_cache, wm8741_reg_defaults, -		sizeof(wm8741->reg_cache)); - -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} -  	for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)  		wm8741->supplies[i].supply = wm8741_supply_names[i]; -	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), +	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),  				 wm8741->supplies);  	if (ret != 0) { -		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); +		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);  		goto err;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),  				    wm8741->supplies);  	if (ret != 0) { -		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); +		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);  		goto err_get;  	} -	ret = wm8741_reset(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err_enable; -	} - -	wm8741_dai.dev = codec->dev; - -	/* Change some default settings - latch VU */ -	wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; -	wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; -	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; -	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; - -	wm8741_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		return ret; -	} - -	ret = snd_soc_register_dai(&wm8741_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); -		return ret; -	} +	i2c_set_clientdata(i2c, wm8741); +	wm8741->control_type = SND_SOC_I2C; -	dev_dbg(codec->dev, "Successful registration\n"); -	return 0; +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8741, &wm8741_dai, 1); +	if (ret < 0) +		goto err_enable; +	return ret;  err_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);  err_get:  	regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); -  err:  	kfree(wm8741);  	return ret;  } -static void wm8741_unregister(struct wm8741_priv *wm8741) -{ -	regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - -	snd_soc_unregister_dai(&wm8741_dai); -	snd_soc_unregister_codec(&wm8741->codec); -	kfree(wm8741); -	wm8741_codec = NULL; -} - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8741_i2c_probe(struct i2c_client *i2c, -				      const struct i2c_device_id *id) -{ -	struct wm8741_priv *wm8741; -	struct snd_soc_codec *codec; - -	wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); -	if (wm8741 == NULL) -		return -ENOMEM; - -	codec = &wm8741->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; - -	i2c_set_clientdata(i2c, wm8741); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; - -	return wm8741_register(wm8741, SND_SOC_I2C); -} - -static __devexit int wm8741_i2c_remove(struct i2c_client *client) +static int wm8741_i2c_remove(struct i2c_client *client)  {  	struct wm8741_priv *wm8741 = i2c_get_clientdata(client); -	wm8741_unregister(wm8741); + +	snd_soc_unregister_codec(&client->dev); +	regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -540,29 +447,29 @@ static const struct i2c_device_id wm8741_i2c_id[] = {  };  MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); -  static struct i2c_driver wm8741_i2c_driver = {  	.driver = { -		.name = "WM8741", +		.name = "wm8741-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8741_i2c_probe, -	.remove =   __devexit_p(wm8741_i2c_remove), +	.remove =   wm8741_i2c_remove,  	.id_table = wm8741_i2c_id,  };  #endif  static int __init wm8741_modinit(void)  { -	int ret; +	int ret = 0; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8741_i2c_driver);  	if (ret != 0) { -		printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n", -		       ret); +		pr_err("Failed to register WM8741 I2C driver: %d\n", ret);  	}  #endif -	return 0; + +	return ret;  }  module_init(wm8741_modinit); diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h index fdef6ecd1f6f..56c1b1d4a681 100644 --- a/sound/soc/codecs/wm8741.h +++ b/sound/soc/codecs/wm8741.h @@ -208,7 +208,4 @@  #define  WM8741_SYSCLK 0 -extern struct snd_soc_dai wm8741_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8741; -  #endif diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index e2c05e3e323a..92d4b2aef93b 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -52,7 +52,7 @@ static const u16 wm8750_reg[] = {  /* codec private data */  struct wm8750_priv {  	unsigned int sysclk; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	u16 reg_cache[ARRAY_SIZE(wm8750_reg)];  }; @@ -560,8 +560,7 @@ static int wm8750_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;  	u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; @@ -649,8 +648,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = {  	.set_sysclk	= wm8750_set_dai_sysclk,  }; -struct snd_soc_dai wm8750_dai = { -	.name = "WM8750", +static struct snd_soc_dai_driver wm8750_dai = { +	.name = "wm8750-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -665,21 +664,15 @@ struct snd_soc_dai wm8750_dai = {  		.formats = WM8750_FORMATS,},  	.ops = &wm8750_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8750_dai); -static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8750_resume(struct platform_device *pdev) +static int wm8750_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -698,100 +691,21 @@ static int wm8750_resume(struct platform_device *pdev)  	return 0;  } -static struct snd_soc_codec *wm8750_codec; - -static int wm8750_probe(struct platform_device *pdev) +static int wm8750_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (!wm8750_codec) { -		dev_err(&pdev->dev, "WM8750 codec not yet registered\n"); -		return -EINVAL; -	} - -	socdev->card->codec = wm8750_codec; -	codec = wm8750_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8750: failed to create pcms\n"); -		goto err; -	} - -	snd_soc_add_controls(codec, wm8750_snd_controls, -				ARRAY_SIZE(wm8750_snd_controls)); -	wm8750_add_widgets(codec); - -	return 0; - -err: -	return ret; -} - -/* power down chip */ -static int wm8750_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_wm8750 = { -	.probe		= wm8750_probe, -	.remove		= wm8750_remove, -	.suspend	= wm8750_suspend, -	.resume		= wm8750_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); - -/* - * initialise the WM8750 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8750_register(struct wm8750_priv *wm8750, -			enum snd_soc_control_type control) -{ -	struct snd_soc_codec *codec = &wm8750->codec; -	int reg, ret = 0; - -	if (wm8750_codec) { -		dev_err(codec->dev, "Multiple WM8750 devices not supported\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "WM8750"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_STANDBY; -	codec->set_bias_level = wm8750_set_bias_level; -	codec->dai = &wm8750_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1; -	codec->reg_cache = &wm8750->reg_cache; -	snd_soc_codec_set_drvdata(codec, wm8750); - -	memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache)); +	struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); +	int reg, ret; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);  	if (ret < 0) {  		printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	ret = wm8750_reset(codec);  	if (ret < 0) {  		printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); -		goto err; +		return ret;  	}  	/* charge output caps */ @@ -815,150 +729,131 @@ static int wm8750_register(struct wm8750_priv *wm8750,  	reg = snd_soc_read(codec, WM8750_RINVOL);  	snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); -	wm8750_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dais(&wm8750_dai, 1); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8750); +	snd_soc_add_controls(codec, wm8750_snd_controls, +				ARRAY_SIZE(wm8750_snd_controls)); +	wm8750_add_widgets(codec);  	return ret;  } -static void wm8750_unregister(struct wm8750_priv *wm8750) +static int wm8750_remove(struct snd_soc_codec *codec)  { -	wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dais(&wm8750_dai, 1); -	snd_soc_unregister_codec(&wm8750->codec); -	kfree(wm8750); -	wm8750_codec = NULL; +	wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8750 2 wire address is determined by GPIO5 - * state during powerup. - *    low  = 0x1a - *    high = 0x1b - */ +static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { +	.probe =	wm8750_probe, +	.remove =	wm8750_remove, +	.suspend =	wm8750_suspend, +	.resume =	wm8750_resume, +	.set_bias_level = wm8750_set_bias_level, +	.reg_cache_size = sizeof(wm8750_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8750_reg, +}; -static int wm8750_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8750_spi_probe(struct spi_device *spi)  { -	struct snd_soc_codec *codec;  	struct wm8750_priv *wm8750; +	int ret;  	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);  	if (wm8750 == NULL)  		return -ENOMEM; -	codec = &wm8750->codec; -	codec->control_data = i2c; -	i2c_set_clientdata(i2c, wm8750); - -	codec->dev = &i2c->dev; +	wm8750->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8750); -	return wm8750_register(wm8750, SND_SOC_I2C); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8750, &wm8750_dai, 1); +	if (ret < 0) +		kfree(wm8750); +	return ret;  } -static int wm8750_i2c_remove(struct i2c_client *client) +static int __devexit wm8750_spi_remove(struct spi_device *spi)  { -	struct wm8750_priv *wm8750 = i2c_get_clientdata(client); -	wm8750_unregister(wm8750); +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  } -static const struct i2c_device_id wm8750_i2c_id[] = { -	{ "wm8750", 0 }, -	{ "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */ -	{ } -}; -MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); - -static struct i2c_driver wm8750_i2c_driver = { +static struct spi_driver wm8750_spi_driver = {  	.driver = { -		.name = "WM8750 I2C Codec", -		.owner = THIS_MODULE, +		.name	= "wm8750-codec", +		.bus	= &spi_bus_type, +		.owner	= THIS_MODULE,  	}, -	.probe =    wm8750_i2c_probe, -	.remove =   wm8750_i2c_remove, -	.id_table = wm8750_i2c_id, +	.probe		= wm8750_spi_probe, +	.remove		= __devexit_p(wm8750_spi_remove),  }; -#endif +#endif /* CONFIG_SPI_MASTER */ -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8750_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_codec *codec;  	struct wm8750_priv *wm8750; +	int ret;  	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);  	if (wm8750 == NULL)  		return -ENOMEM; -	codec = &wm8750->codec; -	codec->control_data = spi; -	codec->dev = &spi->dev; - -	dev_set_drvdata(&spi->dev, wm8750); +	i2c_set_clientdata(i2c, wm8750); +	wm8750->control_type = SND_SOC_I2C; -	return wm8750_register(wm8750, SND_SOC_SPI); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8750, &wm8750_dai, 1); +	if (ret < 0) +		kfree(wm8750); +	return ret;  } -static int __devexit wm8750_spi_remove(struct spi_device *spi) +static __devexit int wm8750_i2c_remove(struct i2c_client *client)  { -	struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); -	wm8750_unregister(wm8750); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } -static const struct spi_device_id wm8750_spi_id[] = { +static const struct i2c_device_id wm8750_i2c_id[] = {  	{ "wm8750", 0 },  	{ "wm8987", 0 },  	{ }  }; -MODULE_DEVICE_TABLE(spi, wm8750_spi_id); +MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); -static struct spi_driver wm8750_spi_driver = { +static struct i2c_driver wm8750_i2c_driver = {  	.driver = { -		.name	= "WM8750 SPI Codec", -		.bus	= &spi_bus_type, -		.owner	= THIS_MODULE, +		.name = "wm8750-codec", +		.owner = THIS_MODULE,  	}, -	.probe		= wm8750_spi_probe, -	.remove		= __devexit_p(wm8750_spi_remove), -	.id_table	= wm8750_spi_id, +	.probe =    wm8750_i2c_probe, +	.remove =   __devexit_p(wm8750_i2c_remove), +	.id_table = wm8750_i2c_id,  };  #endif  static int __init wm8750_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8750_i2c_driver); -	if (ret != 0) -		pr_err("Failed to register WM8750 I2C driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", +		       ret); +	}  #endif  #if defined(CONFIG_SPI_MASTER)  	ret = spi_register_driver(&wm8750_spi_driver); -	if (ret != 0) -		pr_err("Failed to register WM8750 SPI driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n", +		       ret); +	}  #endif -	return 0; +	return ret;  }  module_init(wm8750_modinit); diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h index 1dc100e19cfe..121427c047fb 100644 --- a/sound/soc/codecs/wm8750.h +++ b/sound/soc/codecs/wm8750.h @@ -57,13 +57,4 @@  #define WM8750_SYSCLK	0 -struct wm8750_setup_data { -	int spi; -	int i2c_bus; -	unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8750_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8750; -  #endif diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index b59f349c5218..484423248c26 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -57,7 +57,7 @@ module_param(caps_charge, int, 0);  MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");  static void wm8753_set_dai_mode(struct snd_soc_codec *codec, -	unsigned int mode); +		struct snd_soc_dai *dai, unsigned int hifi);  /*   * wm8753 register cache @@ -85,10 +85,11 @@ static const u16 wm8753_reg[] = {  /* codec private data */  struct wm8753_priv { +	enum snd_soc_control_type control_type;  	unsigned int sysclk;  	unsigned int pcmclk; -	struct snd_soc_codec codec;  	u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; +	int dai_func;  };  /* @@ -228,6 +229,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,  {  	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);  	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])  		return 0; @@ -235,8 +237,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,  	mode &= 0xfff3;  	mode |= (ucontrol->value.integer.value[0] << 2); -	wm8753_write(codec, WM8753_IOCTL, mode); -	wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]); +	wm8753->dai_func =  ucontrol->value.integer.value[0];  	return 1;  } @@ -904,6 +905,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,  	return 0;  } +static int wm8753_pcm_startup(struct snd_pcm_substream *substream, +				struct snd_soc_dai *dai) +{ +	wm8753_set_dai_mode(dai->codec, dai, 0); +	return 0; +} +  /*   * Set PCM DAI bit size and sample rate.   */ @@ -912,8 +920,7 @@ static int wm8753_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;  	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; @@ -1138,6 +1145,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,  	return 0;  } +static int wm8753_i2s_startup(struct snd_pcm_substream *substream, +				struct snd_soc_dai *dai) +{ +	wm8753_set_dai_mode(dai->codec, dai, 1); +	return 0; +} +  /*   * Set PCM DAI bit size and sample rate.   */ @@ -1146,8 +1160,7 @@ static int wm8753_i2s_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;  	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; @@ -1240,12 +1253,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)  {  	struct snd_soc_codec *codec = dai->codec;  	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.  	 * make sure we check if they are not both active when we mute */ -	if (mute && dai->id == 1) { -		if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || -			!wm8753_dai[WM8753_DAI_HIFI].playback.active) +	if (mute && wm8753->dai_func == 1) { +		if (!codec->active)  			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);  	} else {  		if (mute) @@ -1303,6 +1316,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,   * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture   */  static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { +	.startup = wm8753_i2s_startup,  	.hw_params	= wm8753_i2s_hw_params,  	.digital_mute	= wm8753_mute,  	.set_fmt	= wm8753_mode1h_set_dai_fmt, @@ -1312,6 +1326,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {  };  static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { +	.startup = wm8753_pcm_startup,  	.hw_params	= wm8753_pcm_hw_params,  	.digital_mute	= wm8753_mute,  	.set_fmt	= wm8753_mode1v_set_dai_fmt, @@ -1321,6 +1336,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {  };  static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { +	.startup = wm8753_pcm_startup,  	.hw_params	= wm8753_pcm_hw_params,  	.digital_mute	= wm8753_mute,  	.set_fmt	= wm8753_mode2_set_dai_fmt, @@ -1330,6 +1346,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {  };  static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3	= { +	.startup = wm8753_i2s_startup,  	.hw_params	= wm8753_i2s_hw_params,  	.digital_mute	= wm8753_mute,  	.set_fmt	= wm8753_mode3_4_set_dai_fmt, @@ -1339,6 +1356,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3	= {  };  static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4	= { +	.startup = wm8753_i2s_startup,  	.hw_params	= wm8753_i2s_hw_params,  	.digital_mute	= wm8753_mute,  	.set_fmt	= wm8753_mode3_4_set_dai_fmt, @@ -1347,10 +1365,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4	= {  	.set_sysclk	= wm8753_set_dai_sysclk,  }; -static const struct snd_soc_dai wm8753_all_dai[] = { +static struct snd_soc_dai_driver wm8753_all_dai[] = {  /* DAI HiFi mode 1 */ -{	.name = "WM8753 HiFi", -	.id = 1, +{	.name = "wm8753-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -1366,8 +1383,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {  	.ops = &wm8753_dai_ops_hifi_mode1,  },  /* DAI Voice mode 1 */ -{	.name = "WM8753 Voice", -	.id = 1, +{	.name = "wm8753-voice",  	.playback = {  		.stream_name = "Voice Playback",  		.channels_min = 1, @@ -1383,12 +1399,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {  	.ops = &wm8753_dai_ops_voice_mode1,  },  /* DAI HiFi mode 2 - dummy */ -{	.name = "WM8753 HiFi", -	.id = 2, +{	.name = "wm8753-hifi",  },  /* DAI Voice mode 2 */ -{	.name = "WM8753 Voice", -	.id = 2, +{	.name = "wm8753-voice",  	.playback = {  		.stream_name = "Voice Playback",  		.channels_min = 1, @@ -1404,8 +1418,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {  	.ops = &wm8753_dai_ops_voice_mode2,  },  /* DAI HiFi mode 3 */ -{	.name = "WM8753 HiFi", -	.id = 3, +{	.name = "wm8753-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -1421,12 +1434,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {  	.ops = &wm8753_dai_ops_hifi_mode3,  },  /* DAI Voice mode 3 - dummy */ -{	.name = "WM8753 Voice", -	.id = 3, +{	.name = "wm8753-voice",  },  /* DAI HiFi mode 4 */ -{	.name = "WM8753 HiFi", -	.id = 4, +{	.name = "wm8753-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -1442,58 +1453,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = {  	.ops = &wm8753_dai_ops_hifi_mode4,  },  /* DAI Voice mode 4 - dummy */ -{	.name = "WM8753 Voice", -	.id = 4, +{	.name = "wm8753-voice",  },  }; -struct snd_soc_dai wm8753_dai[] = { +static struct snd_soc_dai_driver wm8753_dai[] = {  	{ -		.name = "WM8753 DAI 0", +		.name = "wm8753-aif0",  	},  	{ -		.name = "WM8753 DAI 1", +		.name = "wm8753-aif1",  	},  }; -EXPORT_SYMBOL_GPL(wm8753_dai); -static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) +static void wm8753_set_dai_mode(struct snd_soc_codec *codec, +		struct snd_soc_dai *dai, unsigned int hifi)  { -	if (mode < 4) { -		int playback_active, capture_active, codec_active, pop_wait; -		void *private_data; -		struct list_head list; - -		playback_active = wm8753_dai[0].playback.active; -		capture_active = wm8753_dai[0].capture.active; -		codec_active = wm8753_dai[0].active; -		private_data = wm8753_dai[0].private_data; -		pop_wait = wm8753_dai[0].pop_wait; -		list = wm8753_dai[0].list; -		wm8753_dai[0] = wm8753_all_dai[mode << 1]; -		wm8753_dai[0].playback.active = playback_active; -		wm8753_dai[0].capture.active = capture_active; -		wm8753_dai[0].active = codec_active; -		wm8753_dai[0].private_data = private_data; -		wm8753_dai[0].pop_wait = pop_wait; -		wm8753_dai[0].list = list; - -		playback_active = wm8753_dai[1].playback.active; -		capture_active = wm8753_dai[1].capture.active; -		codec_active = wm8753_dai[1].active; -		private_data = wm8753_dai[1].private_data; -		pop_wait = wm8753_dai[1].pop_wait; -		list = wm8753_dai[1].list; -		wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; -		wm8753_dai[1].playback.active = playback_active; -		wm8753_dai[1].capture.active = capture_active; -		wm8753_dai[1].active = codec_active; -		wm8753_dai[1].private_data = private_data; -		wm8753_dai[1].pop_wait = pop_wait; -		wm8753_dai[1].list = list; +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); + +	if (wm8753->dai_func < 4) { +		if (hifi) +			dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; +		else +			dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];  	} -	wm8753_dai[0].codec = codec; -	wm8753_dai[1].codec = codec; +	wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);  }  static void wm8753_work(struct work_struct *work) @@ -1503,19 +1487,14 @@ static void wm8753_work(struct work_struct *work)  	wm8753_set_bias_level(codec, codec->bias_level);  } -static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8753_resume(struct platform_device *pdev) +static int wm8753_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -1547,41 +1526,6 @@ static int wm8753_resume(struct platform_device *pdev)  	return 0;  } -static struct snd_soc_codec *wm8753_codec; - -static int wm8753_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (!wm8753_codec) { -		dev_err(&pdev->dev, "WM8753 codec not yet registered\n"); -		return -EINVAL; -	} - -	socdev->card->codec = wm8753_codec; -	codec = wm8753_codec; - -	wm8753_set_dai_mode(codec, 0); - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8753: failed to create pcms\n"); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8753_snd_controls, -			     ARRAY_SIZE(wm8753_snd_controls)); -	wm8753_add_widgets(codec); - -	return 0; - -pcm_err: -	return ret; -} -  /*   * This function forces any delayed work to be queued and run.   */ @@ -1601,62 +1545,29 @@ static int run_delayed_work(struct delayed_work *dwork)  	return ret;  } -/* power down chip */ -static int wm8753_remove(struct platform_device *pdev) +static int wm8753_probe(struct snd_soc_codec *codec)  { -	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_wm8753 = { -	.probe = 	wm8753_probe, -	.remove = 	wm8753_remove, -	.suspend = 	wm8753_suspend, -	.resume =	wm8753_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); +	int ret = 0, reg; -static int wm8753_register(struct wm8753_priv *wm8753) -{ -	int ret, i; -	struct snd_soc_codec *codec = &wm8753->codec; -	u16 reg; +	codec->bias_level = SND_SOC_BIAS_OFF; +	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); -	if (wm8753_codec) { -		dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); -		ret = -EINVAL; -		goto err; +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); +	if (ret < 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "WM8753"; -	codec->owner = THIS_MODULE; -	codec->read = wm8753_read_reg_cache; -	codec->write = wm8753_write; -	codec->bias_level = SND_SOC_BIAS_STANDBY; -	codec->set_bias_level = wm8753_set_bias_level; -	codec->dai = wm8753_dai; -	codec->num_dai = 2; -	codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; -	codec->reg_cache = &wm8753->reg_cache; -	snd_soc_codec_set_drvdata(codec, wm8753); - -	memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); -	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); -  	ret = wm8753_reset(codec);  	if (ret < 0) { -		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		dev_err(codec->dev, "Failed to issue reset: %d\n", ret); +		return ret;  	} +	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +	wm8753->dai_func = 0; +  	/* charge output caps */  	wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);  	schedule_delayed_work(&codec->delayed_work, @@ -1684,165 +1595,137 @@ static int wm8753_register(struct wm8753_priv *wm8753)  	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);  	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); -	wm8753_codec = codec; - -	for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) -		wm8753_dai[i].dev = codec->dev; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8753_snd_controls, +			     ARRAY_SIZE(wm8753_snd_controls)); +	wm8753_add_widgets(codec);  	return 0; -err_codec:  	run_delayed_work(&codec->delayed_work); -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8753);  	return ret;  } -static void wm8753_unregister(struct wm8753_priv *wm8753) +/* power down chip */ +static int wm8753_remove(struct snd_soc_codec *codec)  { -	wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); -	run_delayed_work(&wm8753->codec.delayed_work); -	snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); -	snd_soc_unregister_codec(&wm8753->codec); -	kfree(wm8753); -	wm8753_codec = NULL; +	run_delayed_work(&codec->delayed_work); +	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); + +	return 0;  } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { +	.probe =	wm8753_probe, +	.remove =	wm8753_remove, +	.suspend =	wm8753_suspend, +	.resume =	wm8753_resume, +	.set_bias_level = wm8753_set_bias_level, +	.reg_cache_size = sizeof(wm8753_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8753_reg, +}; -static int wm8753_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8753_spi_probe(struct spi_device *spi)  { -	struct snd_soc_codec *codec;  	struct wm8753_priv *wm8753; +	int ret;  	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);  	if (wm8753 == NULL)  		return -ENOMEM; -        codec = &wm8753->codec; -        codec->hw_write = (hw_write_t)i2c_master_send; -        codec->control_data = i2c; -        i2c_set_clientdata(i2c, wm8753); - -        codec->dev = &i2c->dev; +	wm8753->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8753); -	return wm8753_register(wm8753); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); +	if (ret < 0) +		kfree(wm8753); +	return ret;  } -static int wm8753_i2c_remove(struct i2c_client *client) +static int __devexit wm8753_spi_remove(struct spi_device *spi)  { -        struct wm8753_priv *wm8753 = i2c_get_clientdata(client); -        wm8753_unregister(wm8753); -        return 0; +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi)); +	return 0;  } -static const struct i2c_device_id wm8753_i2c_id[] = { -	{ "wm8753", 0 }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); - -static struct i2c_driver wm8753_i2c_driver = { +static struct spi_driver wm8753_spi_driver = {  	.driver = { -		.name = "wm8753", -		.owner = THIS_MODULE, +		.name	= "wm8753-codec", +		.bus	= &spi_bus_type, +		.owner	= THIS_MODULE,  	}, -	.probe =    wm8753_i2c_probe, -	.remove =   wm8753_i2c_remove, -	.id_table = wm8753_i2c_id, +	.probe		= wm8753_spi_probe, +	.remove		= __devexit_p(wm8753_spi_remove),  }; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) -{ -	struct spi_transfer t; -	struct spi_message m; -	u8 msg[2]; - -	if (len <= 0) -		return 0; - -	msg[0] = data[0]; -	msg[1] = data[1]; +#endif /* CONFIG_SPI_MASTER */ -	spi_message_init(&m); -	memset(&t, 0, (sizeof t)); - -	t.tx_buf = &msg[0]; -	t.len = len; - -	spi_message_add_tail(&t, &m); -	spi_sync(spi, &m); - -	return len; -} - -static int __devinit wm8753_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_codec *codec;  	struct wm8753_priv *wm8753; +	int ret;  	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);  	if (wm8753 == NULL)  		return -ENOMEM; -	codec = &wm8753->codec; -	codec->control_data = spi; -	codec->hw_write = (hw_write_t)wm8753_spi_write; -	codec->dev = &spi->dev; - -	dev_set_drvdata(&spi->dev, wm8753); +	i2c_set_clientdata(i2c, wm8753); +	wm8753->control_type = SND_SOC_I2C; -	return wm8753_register(wm8753); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); +	if (ret < 0) +		kfree(wm8753); +	return ret;  } -static int __devexit wm8753_spi_remove(struct spi_device *spi) +static __devexit int wm8753_i2c_remove(struct i2c_client *client)  { -	struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev); -	wm8753_unregister(wm8753); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } -static struct spi_driver wm8753_spi_driver = { +static const struct i2c_device_id wm8753_i2c_id[] = { +	{ "wm8753", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); + +static struct i2c_driver wm8753_i2c_driver = {  	.driver = { -		.name	= "wm8753", -		.bus	= &spi_bus_type, -		.owner	= THIS_MODULE, +		.name = "wm8753-codec", +		.owner = THIS_MODULE,  	}, -	.probe		= wm8753_spi_probe, -	.remove		= __devexit_p(wm8753_spi_remove), +	.probe =    wm8753_i2c_probe, +	.remove =   __devexit_p(wm8753_i2c_remove), +	.id_table = wm8753_i2c_id,  };  #endif  static int __init wm8753_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8753_i2c_driver); -	if (ret != 0) -		pr_err("Failed to register WM8753 I2C driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", +		       ret); +	}  #endif  #if defined(CONFIG_SPI_MASTER)  	ret = spi_register_driver(&wm8753_spi_driver); -	if (ret != 0) -		pr_err("Failed to register WM8753 SPI driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n", +		       ret); +	}  #endif -	return 0; +	return ret;  }  module_init(wm8753_modinit); diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h index 57b2ba244040..94edac144bcb 100644 --- a/sound/soc/codecs/wm8753.h +++ b/sound/soc/codecs/wm8753.h @@ -115,7 +115,4 @@  #define WM8753_DAI_HIFI		0  #define WM8753_DAI_VOICE		1 -extern struct snd_soc_dai wm8753_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm8753; -  #endif diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 4e212ed62ea6..053030679c1a 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -31,20 +31,13 @@  #include "wm8776.h" -static struct snd_soc_codec *wm8776_codec; -struct snd_soc_codec_device soc_codec_dev_wm8776; -  /* codec private data */  struct wm8776_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	u16 reg_cache[WM8776_CACHEREGNUM];  	int sysclk[2];  }; -#ifdef CONFIG_SPI_MASTER -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); -#endif -  static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {  	0x79, 0x79, 0x79, 0xff, 0xff,  /* 4 */  	0xff, 0x00, 0x90, 0x00, 0x00,  /* 9 */ @@ -144,7 +137,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)  	struct snd_soc_codec *codec = dai->codec;  	int reg, iface, master; -	switch (dai->id) { +	switch (dai->driver->id) {  	case WM8776_DAI_DAC:  		reg = WM8776_DACIFCTRL;  		master = 0x80; @@ -233,7 +226,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,  	iface = 0; -	switch (dai->id) { +	switch (dai->driver->id) {  	case WM8776_DAI_DAC:  		iface_reg = WM8776_DACIFCTRL;  		master = 0x80; @@ -267,7 +260,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,  	/* Only need to set MCLK/LRCLK ratio if we're master */  	if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {  		for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { -			if (wm8776->sysclk[dai->id] / params_rate(params) +			if (wm8776->sysclk[dai->driver->id] / params_rate(params)  			    == mclk_ratios[i])  				break;  		} @@ -275,7 +268,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,  		if (i == ARRAY_SIZE(mclk_ratios)) {  			dev_err(codec->dev,  				"Unable to configure MCLK ratio %d/%d\n", -				wm8776->sysclk[dai->id], params_rate(params)); +				wm8776->sysclk[dai->driver->id], params_rate(params));  			return -EINVAL;  		} @@ -305,9 +298,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai,  	struct snd_soc_codec *codec = dai->codec;  	struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); -	BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); +	BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)); -	wm8776->sysclk[dai->id] = freq; +	wm8776->sysclk[dai->driver->id] = freq;  	return 0;  } @@ -357,10 +350,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = {  	.set_sysclk     = wm8776_set_sysclk,  }; -struct snd_soc_dai wm8776_dai[] = { +static struct snd_soc_dai_driver wm8776_dai[] = {  	{ -		.name = "WM8776 Playback", -		.id = WM8776_DAI_DAC, +		.name = "wm8776-hifi-playback", +		.id	= WM8776_DAI_DAC,  		.playback = {  			.stream_name = "Playback",  			.channels_min = 2, @@ -371,8 +364,8 @@ struct snd_soc_dai wm8776_dai[] = {  		.ops = &wm8776_dac_ops,  	},  	{ -		.name = "WM8776 Capture", -		.id = WM8776_DAI_ADC, +		.name = "wm8776-hifi-capture", +		.id	= WM8776_DAI_ADC,  		.capture = {  			.stream_name = "Capture",  			.channels_min = 2, @@ -383,23 +376,17 @@ struct snd_soc_dai wm8776_dai[] = {  		.ops = &wm8776_adc_ops,  	},  }; -EXPORT_SYMBOL_GPL(wm8776_dai);  #ifdef CONFIG_PM -static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8776_resume(struct platform_device *pdev) +static int wm8776_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -422,27 +409,30 @@ static int wm8776_resume(struct platform_device *pdev)  #define wm8776_resume NULL  #endif -static int wm8776_probe(struct platform_device *pdev) +static int wm8776_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; -	if (wm8776_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); +	if (ret < 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm8776_codec; -	codec = wm8776_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = wm8776_reset(codec);  	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto pcm_err; +		dev_err(codec->dev, "Failed to issue reset: %d\n", ret); +		return ret;  	} +	wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + +	/* Latch the update bits; right channel only since we always +	 * update both. */ +	snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); +	snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); +  	snd_soc_add_controls(codec, wm8776_snd_controls,  			     ARRAY_SIZE(wm8776_snd_controls));  	snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, @@ -450,168 +440,56 @@ static int wm8776_probe(struct platform_device *pdev)  	snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));  	return ret; - -pcm_err: -	return ret;  }  /* power down chip */ -static int wm8776_remove(struct platform_device *pdev) +static int wm8776_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - +	wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm8776 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {  	.probe = 	wm8776_probe,  	.remove = 	wm8776_remove,  	.suspend = 	wm8776_suspend,  	.resume =	wm8776_resume, +	.set_bias_level = wm8776_set_bias_level, +	.reg_cache_size = sizeof(wm8776_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8776_reg,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); - -static int wm8776_register(struct wm8776_priv *wm8776, -			   enum snd_soc_control_type control) -{ -	int ret, i; -	struct snd_soc_codec *codec = &wm8776->codec; - -	if (wm8776_codec) { -		dev_err(codec->dev, "Another WM8776 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8776); -	codec->name = "WM8776"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8776_set_bias_level; -	codec->dai = wm8776_dai; -	codec->num_dai = ARRAY_SIZE(wm8776_dai); -	codec->reg_cache_size = WM8776_CACHEREGNUM; -	codec->reg_cache = &wm8776->reg_cache; - -	memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} - -	for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) -		wm8776_dai[i].dev = codec->dev; - -	ret = wm8776_reset(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to issue reset: %d\n", ret); -		goto err; -	} - -	wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -	/* Latch the update bits; right channel only since we always -	 * update both. */ -	snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); -	snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); - -	wm8776_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8776); -	return ret; -} - -static void wm8776_unregister(struct wm8776_priv *wm8776) -{ -	wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); -	snd_soc_unregister_codec(&wm8776->codec); -	kfree(wm8776); -	wm8776_codec = NULL; -}  #if defined(CONFIG_SPI_MASTER) -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) -{ -	struct spi_transfer t; -	struct spi_message m; -	u8 msg[2]; - -	if (len <= 0) -		return 0; - -	msg[0] = data[0]; -	msg[1] = data[1]; - -	spi_message_init(&m); -	memset(&t, 0, (sizeof t)); - -	t.tx_buf = &msg[0]; -	t.len = len; - -	spi_message_add_tail(&t, &m); -	spi_sync(spi, &m); - -	return len; -} -  static int __devinit wm8776_spi_probe(struct spi_device *spi)  { -	struct snd_soc_codec *codec;  	struct wm8776_priv *wm8776; +	int ret;  	wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);  	if (wm8776 == NULL)  		return -ENOMEM; -	codec = &wm8776->codec; -	codec->control_data = spi; -	codec->hw_write = (hw_write_t)wm8776_spi_write; -	codec->dev = &spi->dev; +	wm8776->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8776); -	dev_set_drvdata(&spi->dev, wm8776); - -	return wm8776_register(wm8776, SND_SOC_SPI); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); +	if (ret < 0) +		kfree(wm8776); +	return ret;  }  static int __devexit wm8776_spi_remove(struct spi_device *spi)  { -	struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); - -	wm8776_unregister(wm8776); - +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver wm8776_spi_driver = {  	.driver = { -		.name	= "wm8776", +		.name	= "wm8776-codec",  		.bus	= &spi_bus_type,  		.owner	= THIS_MODULE,  	}, @@ -625,27 +503,26 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8776_priv *wm8776; -	struct snd_soc_codec *codec; +	int ret;  	wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);  	if (wm8776 == NULL)  		return -ENOMEM; -	codec = &wm8776->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, wm8776); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm8776->control_type = SND_SOC_I2C; -	return wm8776_register(wm8776, SND_SOC_I2C); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); +	if (ret < 0) +		kfree(wm8776); +	return ret;  }  static __devexit int wm8776_i2c_remove(struct i2c_client *client)  { -	struct wm8776_priv *wm8776 = i2c_get_clientdata(client); -	wm8776_unregister(wm8776); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -657,7 +534,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);  static struct i2c_driver wm8776_i2c_driver = {  	.driver = { -		.name = "wm8776", +		.name = "wm8776-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8776_i2c_probe, @@ -668,22 +545,22 @@ static struct i2c_driver wm8776_i2c_driver = {  static int __init wm8776_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8776_i2c_driver);  	if (ret != 0) { -		printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", +		printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n",  		       ret);  	}  #endif  #if defined(CONFIG_SPI_MASTER)  	ret = spi_register_driver(&wm8776_spi_driver);  	if (ret != 0) { -		printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", +		printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n",  		       ret);  	}  #endif -	return 0; +	return ret;  }  module_init(wm8776_modinit); diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h index 6606d25d2d83..4cf1c8e0bfc9 100644 --- a/sound/soc/codecs/wm8776.h +++ b/sound/soc/codecs/wm8776.h @@ -45,7 +45,4 @@  #define WM8776_DAI_DAC 0  #define WM8776_DAI_ADC 1 -extern struct snd_soc_dai wm8776_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8776; -  #endif diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..1378aab5ca75 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -23,6 +23,7 @@  #include <linux/delay.h>  #include <linux/pm.h>  #include <linux/i2c.h> +#include <linux/spi/spi.h>  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <sound/core.h> @@ -137,11 +138,8 @@  #define WM8900_LRC_MASK 0xfc00 -struct snd_soc_codec_device soc_codec_dev_wm8900; -  struct wm8900_priv { -	struct snd_soc_codec codec; - +	enum snd_soc_control_type control_type;  	u16 reg_cache[WM8900_MAXREG];  	u32 fll_in; /* FLL input frequency */ @@ -627,8 +625,7 @@ static int wm8900_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 reg;  	reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; @@ -1015,8 +1012,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = {  	.digital_mute	= wm8900_digital_mute,  }; -struct snd_soc_dai wm8900_dai = { -	.name = "WM8900 HiFi", +static struct snd_soc_dai_driver wm8900_dai = { +	.name = "wm8900-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -1033,7 +1030,6 @@ struct snd_soc_dai wm8900_dai = {  	 },  	.ops = &wm8900_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8900_dai);  static int wm8900_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level) @@ -1128,10 +1124,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,  	return 0;  } -static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);  	int fll_out = wm8900->fll_out;  	int fll_in  = wm8900->fll_in; @@ -1140,7 +1134,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)  	/* Stop the FLL in an orderly fashion */  	ret = wm8900_set_fll(codec, 0, 0, 0);  	if (ret != 0) { -		dev_err(&pdev->dev, "Failed to stop FLL\n"); +		dev_err(codec->dev, "Failed to stop FLL\n");  		return ret;  	} @@ -1152,10 +1146,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)  	return 0;  } -static int wm8900_resume(struct platform_device *pdev) +static int wm8900_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);  	u16 *cache;  	int i, ret; @@ -1176,7 +1168,7 @@ static int wm8900_resume(struct platform_device *pdev)  		ret = wm8900_set_fll(codec, 0, fll_in, fll_out);  		if (ret != 0) { -			dev_err(&pdev->dev, "Failed to restart FLL\n"); +			dev_err(codec->dev, "Failed to restart FLL\n");  			return ret;  		}  	} @@ -1186,60 +1178,32 @@ static int wm8900_resume(struct platform_device *pdev)  			snd_soc_write(codec, i, cache[i]);  		kfree(cache);  	} else -		dev_err(&pdev->dev, "Unable to allocate register cache\n"); +		dev_err(codec->dev, "Unable to allocate register cache\n");  	return 0;  } -static struct snd_soc_codec *wm8900_codec; - -static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, -				      const struct i2c_device_id *id) +static int wm8900_probe(struct snd_soc_codec *codec)  { -	struct wm8900_priv *wm8900; -	struct snd_soc_codec *codec; -	unsigned int reg; -	int ret; - -	wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); -	if (wm8900 == NULL) -		return -ENOMEM; +	struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); +	int ret = 0, reg; -	codec = &wm8900->codec; -	snd_soc_codec_set_drvdata(codec, wm8900); -	codec->reg_cache = &wm8900->reg_cache[0]; -	codec->reg_cache_size = WM8900_MAXREG; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "WM8900"; -	codec->owner = THIS_MODULE; -	codec->dai = &wm8900_dai; -	codec->num_dai = 1; -	codec->control_data = i2c; -	codec->set_bias_level = wm8900_set_bias_level; -	codec->volatile_register = wm8900_volatile_register; -	codec->dev = &i2c->dev; - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type);  	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	}  	reg = snd_soc_read(codec, WM8900_REG_ID);  	if (reg != 0x8900) { -		dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); -		ret = -ENODEV; -		goto err; +		dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); +		return -ENODEV;  	}  	/* Read back from the chip */  	reg = snd_soc_read(codec, WM8900_REG_POWER1);  	reg = (reg >> 12) & 0xf; -	dev_info(&i2c->dev, "WM8900 revision %d\n", reg); +	dev_info(codec->dev, "WM8900 revision %d\n", reg);  	wm8900_reset(codec); @@ -1271,43 +1235,95 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,  	/* Set the DAC and mixer output bias */  	snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); -	wm8900_dai.dev = &i2c->dev; +	snd_soc_add_controls(codec, wm8900_snd_controls, +				ARRAY_SIZE(wm8900_snd_controls)); +	wm8900_add_widgets(codec); -	wm8900_codec = codec; +	return 0; +} -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} +/* power down chip */ +static int wm8900_remove(struct snd_soc_codec *codec) +{ +	wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0; +} -	ret = snd_soc_register_dai(&wm8900_dai); -	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { +	.probe =	wm8900_probe, +	.remove =	wm8900_remove, +	.suspend =	wm8900_suspend, +	.resume =	wm8900_resume, +	.set_bias_level = wm8900_set_bias_level, +	.volatile_register = wm8900_volatile_register, +	.reg_cache_size = sizeof(wm8900_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8900_reg_defaults, +}; -	return ret; +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8900_spi_probe(struct spi_device *spi) +{ +	struct wm8900_priv *wm8900; +	int ret; + +	wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); +	if (wm8900 == NULL) +		return -ENOMEM; -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8900); -	wm8900_codec = NULL; +	wm8900->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8900); + +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8900, &wm8900_dai, 1); +	if (ret < 0) +		kfree(wm8900);  	return ret;  } -static __devexit int wm8900_i2c_remove(struct i2c_client *client) +static int __devexit wm8900_spi_remove(struct spi_device *spi)  { -	snd_soc_unregister_dai(&wm8900_dai); -	snd_soc_unregister_codec(wm8900_codec); +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi)); +	return 0; +} -	wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); +static struct spi_driver wm8900_spi_driver = { +	.driver = { +		.name	= "wm8900-codec", +		.bus	= &spi_bus_type, +		.owner	= THIS_MODULE, +	}, +	.probe		= wm8900_spi_probe, +	.remove		= __devexit_p(wm8900_spi_remove), +}; +#endif /* CONFIG_SPI_MASTER */ + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id) +{ +	struct wm8900_priv *wm8900; +	int ret; + +	wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); +	if (wm8900 == NULL) +		return -ENOMEM; + +	i2c_set_clientdata(i2c, wm8900); +	wm8900->control_type = SND_SOC_I2C; -	wm8900_dai.dev = NULL; -	kfree(snd_soc_codec_get_drvdata(wm8900_codec)); -	wm8900_codec = NULL; +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8900, &wm8900_dai, 1); +	if (ret < 0) +		kfree(wm8900); +	return ret; +} +static __devexit int wm8900_i2c_remove(struct i2c_client *client) +{ +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1319,71 +1335,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);  static struct i2c_driver wm8900_i2c_driver = {  	.driver = { -		.name = "WM8900", +		.name = "wm8900-codec",  		.owner = THIS_MODULE,  	}, -	.probe = wm8900_i2c_probe, -	.remove = __devexit_p(wm8900_i2c_remove), +	.probe =    wm8900_i2c_probe, +	.remove =   __devexit_p(wm8900_i2c_remove),  	.id_table = wm8900_i2c_id,  }; +#endif -static int wm8900_probe(struct platform_device *pdev) +static int __init wm8900_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec;  	int ret = 0; - -	if (!wm8900_codec) { -		dev_err(&pdev->dev, "I2C client not yet instantiated\n"); -		return -ENODEV; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8900_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", +		       ret);  	} - -	codec = wm8900_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 register new PCMs\n"); -		goto pcm_err; +#endif +#if defined(CONFIG_SPI_MASTER) +	ret = spi_register_driver(&wm8900_spi_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", +		       ret);  	} - -	snd_soc_add_controls(codec, wm8900_snd_controls, -				ARRAY_SIZE(wm8900_snd_controls)); -	wm8900_add_widgets(codec); - -pcm_err: +#endif  	return ret;  } - -/* power down chip */ -static int wm8900_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_wm8900 = { -	.probe = 	wm8900_probe, -	.remove = 	wm8900_remove, -	.suspend = 	wm8900_suspend, -	.resume =	wm8900_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); - -static int __init wm8900_modinit(void) -{ -	return i2c_add_driver(&wm8900_i2c_driver); -}  module_init(wm8900_modinit);  static void __exit wm8900_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8900_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) +	spi_unregister_driver(&wm8900_spi_driver); +#endif  }  module_exit(wm8900_exit); diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index fd15007d10c7..583f257e799b 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h @@ -52,7 +52,4 @@  #define WM8900_DAC_CLKDIV_5_5 0x14  #define WM8900_DAC_CLKDIV_6   0x18 -extern struct snd_soc_dai wm8900_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8900; -  #endif diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bf08282d5ee5..622b60238a82 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -213,10 +213,11 @@ static u16 wm8903_reg_defaults[] = {  };  struct wm8903_priv { -	struct snd_soc_codec codec; +  	u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];  	int sysclk; +	int irq;  	/* Reference counts */  	int class_w_users; @@ -252,7 +253,6 @@ static int wm8903_volatile_register(unsigned int reg)  static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)  {  	u16 reg[5]; -	struct i2c_client *i2c = codec->control_data;  	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);  	BUG_ON(start > 48); @@ -262,7 +262,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)  	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,  		      reg[0] | WM8903_WSEQ_ENA); -	dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); +	dev_dbg(codec->dev, "Starting sequence at %d\n", start);  	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,  		     start | WM8903_WSEQ_START); @@ -277,7 +277,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)  		reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);  	} while (reg[4] & WM8903_WSEQ_BUSY); -	dev_dbg(&i2c->dev, "Sequence complete\n"); +	dev_dbg(codec->dev, "Sequence complete\n");  	/* Disable the sequencer again if we enabled it */  	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); @@ -422,7 +422,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,  	struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);  	struct snd_soc_codec *codec = widget->codec;  	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); -	struct i2c_client *i2c = codec->control_data;  	u16 reg;  	int ret; @@ -431,7 +430,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,  	/* Turn it off if we're about to enable bypass */  	if (ucontrol->value.integer.value[0]) {  		if (wm8903->class_w_users == 0) { -			dev_dbg(&i2c->dev, "Disabling Class W\n"); +			dev_dbg(codec->dev, "Disabling Class W\n");  			snd_soc_write(codec, WM8903_CLASS_W_0, reg &  				     ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));  		} @@ -444,14 +443,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,  	/* If we've just disabled the last bypass path turn Class W on */  	if (!ucontrol->value.integer.value[0]) {  		if (wm8903->class_w_users == 1) { -			dev_dbg(&i2c->dev, "Enabling Class W\n"); +			dev_dbg(codec->dev, "Enabling Class W\n");  			snd_soc_write(codec, WM8903_CLASS_W_0, reg |  				     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);  		}  		wm8903->class_w_users--;  	} -	dev_dbg(&i2c->dev, "Bypass use count now %d\n", +	dev_dbg(codec->dev, "Bypass use count now %d\n",  		wm8903->class_w_users);  	return ret; @@ -935,7 +934,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)  static int wm8903_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level)  { -	struct i2c_client *i2c = codec->control_data;  	u16 reg, reg2;  	switch (level) { @@ -974,7 +972,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,  			/* By default no bypass paths are enabled so  			 * enable Class W support.  			 */ -			dev_dbg(&i2c->dev, "Enabling Class W\n"); +			dev_dbg(codec->dev, "Enabling Class W\n");  			snd_soc_write(codec, WM8903_CLASS_W_0, reg |  				     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);  		} @@ -1228,10 +1226,8 @@ static int wm8903_startup(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); -	struct i2c_client *i2c = codec->control_data;  	struct snd_pcm_runtime *master_runtime;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1245,7 +1241,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream,  	if (wm8903->master_substream) {  		master_runtime = wm8903->master_substream->runtime; -		dev_dbg(&i2c->dev, "Constraining to %d bits\n", +		dev_dbg(codec->dev, "Constraining to %d bits\n",  			master_runtime->sample_bits);  		snd_pcm_hw_constraint_minmax(substream->runtime, @@ -1264,8 +1260,7 @@ static void wm8903_shutdown(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1284,10 +1279,8 @@ static int wm8903_hw_params(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; +	struct snd_soc_codec *codec =rtd->codec;  	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); -	struct i2c_client *i2c = codec->control_data;  	int fs = params_rate(params);  	int bclk;  	int bclk_div; @@ -1306,7 +1299,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  	u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);  	if (substream == wm8903->slave_substream) { -		dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); +		dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");  		return 0;  	} @@ -1332,7 +1325,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  		switch (sample_rates[dsp_config].rate) {  		case 88200:  		case 96000: -			dev_err(&i2c->dev, "%dHz unsupported by ADC\n", +			dev_err(codec->dev, "%dHz unsupported by ADC\n",  				fs);  			return -EINVAL; @@ -1340,7 +1333,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  			break;  		} -	dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); +	dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);  	clock1 &= ~WM8903_SAMPLE_RATE_MASK;  	clock1 |= sample_rates[dsp_config].value; @@ -1366,7 +1359,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", +	dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n",  		wm8903->sysclk, fs);  	/* We may not have an MCLK which allows us to generate exactly @@ -1401,12 +1394,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  	clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT;  	clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; -	dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", +	dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",  		clk_sys_ratios[clk_config].rate,  		clk_sys_ratios[clk_config].mode,  		clk_sys_ratios[clk_config].div); -	dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); +	dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys);  	/* We may not get quite the right frequency if using  	 * approximate clocks so look for the closest match that is @@ -1428,7 +1421,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,  	aif2 &= ~WM8903_BCLK_DIV_MASK;  	aif3 &= ~WM8903_LRCLK_RATE_MASK; -	dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", +	dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",  		bclk_divs[bclk_div].ratio / 10, bclk,  		(clk_sys * 10) / bclk_divs[bclk_div].ratio); @@ -1504,8 +1497,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);  static irqreturn_t wm8903_irq(int irq, void *data)  { -	struct wm8903_priv *wm8903 = data; -	struct snd_soc_codec *codec = &wm8903->codec; +	struct snd_soc_codec *codec = data; +	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);  	int mic_report;  	int int_pol;  	int int_val = 0; @@ -1586,8 +1579,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = {  	.set_sysclk	= wm8903_set_dai_sysclk,  }; -struct snd_soc_dai wm8903_dai = { -	.name = "WM8903", +static struct snd_soc_dai_driver wm8903_dai = { +	.name = "wm8903-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -1605,23 +1598,16 @@ struct snd_soc_dai wm8903_dai = {  	.ops = &wm8903_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8903_dai); -static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8903_resume(struct platform_device *pdev) +static int wm8903_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -	struct i2c_client *i2c = codec->control_data;  	int i;  	u16 *reg_cache = codec->reg_cache;  	u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), @@ -1637,65 +1623,37 @@ static int wm8903_resume(struct platform_device *pdev)  				snd_soc_write(codec, i, tmp_cache[i]);  		kfree(tmp_cache);  	} else { -		dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); +		dev_err(codec->dev, "Failed to allocate temporary cache\n");  	}  	return 0;  } -static struct snd_soc_codec *wm8903_codec; - -static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, -				      const struct i2c_device_id *id) +static int wm8903_probe(struct snd_soc_codec *codec)  { -	struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); -	struct wm8903_priv *wm8903; -	struct snd_soc_codec *codec; +	struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); +	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);  	int ret, i;  	int trigger, irq_pol;  	u16 val; -	wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); -	if (wm8903 == NULL) -		return -ENOMEM; - -	codec = &wm8903->codec; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->dev = &i2c->dev; -	codec->name = "WM8903"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8903_set_bias_level; -	codec->dai = &wm8903_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); -	codec->reg_cache = &wm8903->reg_cache[0]; -	snd_soc_codec_set_drvdata(codec, wm8903); -	codec->volatile_register = wm8903_volatile_register;  	init_completion(&wm8903->wseq); -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; -  	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);  	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	}  	val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);  	if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { -		dev_err(&i2c->dev, +		dev_err(codec->dev,  			"Device with ID register %x is not a WM8903\n", val);  		return -ENODEV;  	}  	val = snd_soc_read(codec, WM8903_REVISION_NUMBER); -	dev_info(&i2c->dev, "WM8903 revision %d\n", +	dev_info(codec->dev, "WM8903 revision %d\n",  		 val & WM8903_CHIP_REV_MASK);  	wm8903_reset(codec); @@ -1721,7 +1679,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,  		wm8903->mic_delay = pdata->micdet_delay;  	} -	if (i2c->irq) { +	if (wm8903->irq) {  		if (pdata && pdata->irq_active_low) {  			trigger = IRQF_TRIGGER_LOW;  			irq_pol = WM8903_IRQ_POL; @@ -1733,13 +1691,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,  		snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,  				    WM8903_IRQ_POL, irq_pol); -		ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, +		ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,  					   trigger | IRQF_ONESHOT, -					   "wm8903", wm8903); +					   "wm8903", codec);  		if (ret != 0) { -			dev_err(&i2c->dev, "Failed to request IRQ: %d\n", +			dev_err(codec->dev, "Failed to request IRQ: %d\n",  				ret); -			goto err; +			return ret;  		}  		/* Enable write sequencer interrupts */ @@ -1781,133 +1739,96 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,  	val |= WM8903_DAC_MUTEMODE;  	snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); -	wm8903_dai.dev = &i2c->dev; -	wm8903_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); -		goto err_irq; -	} - -	ret = snd_soc_register_dai(&wm8903_dai); -	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return ret; +	snd_soc_add_controls(codec, wm8903_snd_controls, +				ARRAY_SIZE(wm8903_snd_controls)); +	wm8903_add_widgets(codec); -err_codec: -	snd_soc_unregister_codec(codec); -err_irq: -	if (i2c->irq) -		free_irq(i2c->irq, wm8903); -err: -	wm8903_codec = NULL; -	kfree(wm8903);  	return ret;  } -static __devexit int wm8903_i2c_remove(struct i2c_client *client) +/* power down chip */ +static int wm8903_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); +	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0; +} -	snd_soc_unregister_dai(&wm8903_dai); -	snd_soc_unregister_codec(codec); +static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { +	.probe =	wm8903_probe, +	.remove =	wm8903_remove, +	.suspend =	wm8903_suspend, +	.resume =	wm8903_resume, +	.set_bias_level = wm8903_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8903_reg_defaults, +	.volatile_register = wm8903_volatile_register, +}; -	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id) +{ +	struct wm8903_priv *wm8903; +	int ret; -	if (client->irq) -		free_irq(client->irq, priv); +	wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); +	if (wm8903 == NULL) +		return -ENOMEM; -	kfree(priv); +	i2c_set_clientdata(i2c, wm8903); +	wm8903->irq = i2c->irq; -	wm8903_codec = NULL; -	wm8903_dai.dev = NULL; +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8903, &wm8903_dai, 1); +	if (ret < 0) +		kfree(wm8903); +	return ret; +} +static __devexit int wm8903_i2c_remove(struct i2c_client *client) +{ +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } -/* i2c codec control layer */  static const struct i2c_device_id wm8903_i2c_id[] = { -       { "wm8903", 0 }, -       { } +	{ "wm8903", 0 }, +	{ }  };  MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);  static struct i2c_driver wm8903_i2c_driver = {  	.driver = { -		.name = "WM8903", +		.name = "wm8903-codec",  		.owner = THIS_MODULE,  	}, -	.probe    = wm8903_i2c_probe, -	.remove   = __devexit_p(wm8903_i2c_remove), +	.probe =    wm8903_i2c_probe, +	.remove =   __devexit_p(wm8903_i2c_remove),  	.id_table = wm8903_i2c_id,  }; +#endif -static int wm8903_probe(struct platform_device *pdev) +static int __init wm8903_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev);  	int ret = 0; - -	if (!wm8903_codec) { -		dev_err(&pdev->dev, "I2C device not yet probed\n"); -		goto err; -	} - -	socdev->card->codec = wm8903_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 err; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8903_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", +		       ret);  	} - -	snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, -				ARRAY_SIZE(wm8903_snd_controls)); -	wm8903_add_widgets(socdev->card->codec); - +#endif  	return ret; - -err: -	return ret; -} - -/* power down chip */ -static int wm8903_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8903 = { -	.probe = 	wm8903_probe, -	.remove = 	wm8903_remove, -	.suspend = 	wm8903_suspend, -	.resume =	wm8903_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); - -static int __init wm8903_modinit(void) -{ -	return i2c_add_driver(&wm8903_i2c_driver);  }  module_init(wm8903_modinit);  static void __exit wm8903_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8903_i2c_driver); +#endif  }  module_exit(wm8903_exit); diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index ce384a2ad820..996435e681e5 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h @@ -15,9 +15,6 @@  #include <linux/i2c.h> -extern struct snd_soc_dai wm8903_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8903; -  extern int wm8903_mic_detect(struct snd_soc_codec *codec,  			     struct snd_soc_jack *jack,  			     int det, int shrt); diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7dcabf6283c..33be84e506ea 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -31,9 +31,6 @@  #include "wm8904.h" -static struct snd_soc_codec *wm8904_codec; -struct snd_soc_codec_device soc_codec_dev_wm8904; -  enum wm8904_type {  	WM8904,  	WM8912, @@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {  /* codec private data */  struct wm8904_priv { -	struct snd_soc_codec codec; +  	u16 reg_cache[WM8904_MAX_REGISTER + 1];  	enum wm8904_type devtype; +	void *control_data;  	struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; @@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,  			       struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);	 +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata;  	int value = ucontrol->value.integer.value[0]; @@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,  					 struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);	 +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata;  	int value = ucontrol->value.integer.value[0]; @@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = {  	.digital_mute = wm8904_digital_mute,  }; -struct snd_soc_dai wm8904_dai = { -	.name = "WM8904", +static struct snd_soc_dai_driver wm8904_dai = { +	.name = "wm8904-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = {  	.ops = &wm8904_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8904_dai);  #ifdef CONFIG_PM -static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8904_resume(struct platform_device *pdev) +static int wm8904_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev)  #define wm8904_resume NULL  #endif -static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) +static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = &wm8904->codec; +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata;  	struct snd_kcontrol_new control =  		SOC_ENUM_EXT("EQ Mode", @@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)  	wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;  	wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; -	ret = snd_soc_add_controls(&wm8904->codec, &control, 1); +	ret = snd_soc_add_controls(codec, &control, 1);  	if (ret != 0) -		dev_err(wm8904->codec.dev, +		dev_err(codec->dev,  			"Failed to add ReTune Mobile control: %d\n", ret);  } -static void wm8904_handle_pdata(struct wm8904_priv *wm8904) +static void wm8904_handle_pdata(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = &wm8904->codec; +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata;  	int ret, i;  	if (!pdata) { -		snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, +		snd_soc_add_controls(codec, wm8904_eq_controls,  				     ARRAY_SIZE(wm8904_eq_controls));  		return;  	} @@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)  		wm8904->drc_texts = kmalloc(sizeof(char *)  					    * pdata->num_drc_cfgs, GFP_KERNEL);  		if (!wm8904->drc_texts) { -			dev_err(wm8904->codec.dev, +			dev_err(codec->dev,  				"Failed to allocate %d DRC config texts\n",  				pdata->num_drc_cfgs);  			return; @@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)  		wm8904->drc_enum.max = pdata->num_drc_cfgs;  		wm8904->drc_enum.texts = wm8904->drc_texts; -		ret = snd_soc_add_controls(&wm8904->codec, &control, 1); +		ret = snd_soc_add_controls(codec, &control, 1);  		if (ret != 0) -			dev_err(wm8904->codec.dev, +			dev_err(codec->dev,  				"Failed to add DRC mode control: %d\n", ret);  		wm8904_set_drc(codec); @@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)  		pdata->num_retune_mobile_cfgs);  	if (pdata->num_retune_mobile_cfgs) -		wm8904_handle_retune_mobile_pdata(wm8904); +		wm8904_handle_retune_mobile_pdata(codec);  	else -		snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, +		snd_soc_add_controls(codec, wm8904_eq_controls,  				     ARRAY_SIZE(wm8904_eq_controls));  } -static int wm8904_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8904_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} -	socdev->card->codec = wm8904_codec; -	codec = wm8904_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: %d\n", ret); -		goto pcm_err; -	} - -	wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec)); - -	wm8904_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -static int wm8904_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_wm8904 = { -	.probe = 	wm8904_probe, -	.remove = 	wm8904_remove, -	.suspend = 	wm8904_suspend, -	.resume =	wm8904_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904); - -static int wm8904_register(struct wm8904_priv *wm8904, -			   enum snd_soc_control_type control) +static int wm8904_probe(struct snd_soc_codec *codec)  { +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata; -	int ret; -	struct snd_soc_codec *codec = &wm8904->codec; -	int i; - -	if (wm8904_codec) { -		dev_err(codec->dev, "Another WM8904 is registered\n"); -		ret = -EINVAL; -		goto err; -	} +	int ret, i; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8904); -	codec->name = "WM8904"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8904_set_bias_level; -	codec->dai = &wm8904_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8904_MAX_REGISTER; -	codec->reg_cache = &wm8904->reg_cache; -	codec->volatile_register = wm8904_volatile_register;  	codec->cache_sync = 1;  	codec->idle_bias_off = 1; @@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904,  	default:  		dev_err(codec->dev, "Unknown device type %d\n",  			wm8904->devtype); -		ret = -EINVAL; -		goto err; +		return -EINVAL;  	} -	memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) @@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904,  				 wm8904->supplies);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; +		return ret;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), @@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904,  		goto err_enable;  	} -	wm8904_dai.dev = codec->dev; -  	/* Change some default settings - latch VU and enable ZC */  	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;  	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; @@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904,  	/* Bias level configuration will have done an extra enable */  	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); -	wm8904_codec = codec; +	wm8904_handle_pdata(codec); -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_enable; -	} - -	ret = snd_soc_register_dai(&wm8904_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	wm8904_add_widgets(codec);  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);  err_get:  	regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); -err: -	kfree(wm8904);  	return ret;  } -static void wm8904_unregister(struct wm8904_priv *wm8904) +static int wm8904_remove(struct snd_soc_codec *codec)  { -	wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); +	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + +	wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);  	regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); -	snd_soc_unregister_dai(&wm8904_dai); -	snd_soc_unregister_codec(&wm8904->codec); -	kfree(wm8904); -	wm8904_codec = NULL; + +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { +	.probe =	wm8904_probe, +	.remove =	wm8904_remove, +	.suspend =	wm8904_suspend, +	.resume =	wm8904_resume, +	.set_bias_level = wm8904_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8904_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8904_reg, +	.volatile_register = wm8904_volatile_register, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8904_priv *wm8904; -	struct snd_soc_codec *codec; +	int ret;  	wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);  	if (wm8904 == NULL)  		return -ENOMEM; -	codec = &wm8904->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	wm8904->devtype = id->driver_data; -  	i2c_set_clientdata(i2c, wm8904); -	codec->control_data = i2c; +	wm8904->control_data = i2c;  	wm8904->pdata = i2c->dev.platform_data; -	codec->dev = &i2c->dev; - -	return wm8904_register(wm8904, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8904, &wm8904_dai, 1); +	if (ret < 0) +		kfree(wm8904); +	return ret;  }  static __devexit int wm8904_i2c_remove(struct i2c_client *client)  { -	struct wm8904_priv *wm8904 = i2c_get_clientdata(client); -	wm8904_unregister(wm8904); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);  static struct i2c_driver wm8904_i2c_driver = {  	.driver = { -		.name = "WM8904", +		.name = "wm8904-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8904_i2c_probe, @@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = {  static int __init wm8904_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8904_i2c_driver);  	if (ret != 0) { -		printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", +		printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",  		       ret);  	}  #endif -	return 0; +	return ret;  }  module_init(wm8904_modinit); diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h index abe5059b3004..9e8c84188ba7 100644 --- a/sound/soc/codecs/wm8904.h +++ b/sound/soc/codecs/wm8904.h @@ -21,9 +21,6 @@  #define WM8904_FLL_LRCLK         3  #define WM8904_FLL_FREE_RUNNING  4 -extern struct snd_soc_dai wm8904_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8904; -  /*   * Register values.   */ diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index f0c11138e610..d28bf0dfdb1d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -44,7 +44,8 @@  struct wm8940_priv {  	unsigned int sysclk;  	u16 reg_cache[WM8940_CACHEREGNUM]; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  };  static u16 wm8940_reg_defaults[] = { @@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;  	u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;  	u16 companding =  snd_soc_read(codec, @@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = {  	.set_pll = wm8940_set_dai_pll,  }; -struct snd_soc_dai wm8940_dai = { -	.name = "WM8940", +static struct snd_soc_dai_driver wm8940_dai = { +	.name = "wm8940-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = {  	.ops = &wm8940_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8940_dai); -static int wm8940_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);  } -static int wm8940_resume(struct platform_device *pdev) +static int wm8940_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	int ret;  	u8 data[3]; @@ -697,108 +691,26 @@ error_ret:  	return ret;  } -static struct snd_soc_codec *wm8940_codec; - -static int wm8940_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; - -	int ret = 0; - -	if (wm8940_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8940_codec; -	codec = wm8940_codec; - -	mutex_init(&codec->mutex); -	/* 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: %d\n", ret); -		goto pcm_err; -	} - -	ret = snd_soc_add_controls(codec, wm8940_snd_controls, -			     ARRAY_SIZE(wm8940_snd_controls)); -	if (ret) -		goto error_free_pcms; -	ret = wm8940_add_widgets(codec); -	if (ret) -		goto error_free_pcms; - -	return ret; - -error_free_pcms: -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); -pcm_err: -	return ret; -} - -static int wm8940_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_wm8940 = { -	.probe = wm8940_probe, -	.remove = wm8940_remove, -	.suspend = wm8940_suspend, -	.resume = wm8940_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940); - -static int wm8940_register(struct wm8940_priv *wm8940, -			   enum snd_soc_control_type control) +static int wm8940_probe(struct snd_soc_codec *codec)  { -	struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; -	struct snd_soc_codec *codec = &wm8940->codec; +	struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); +	struct wm8940_setup_data *pdata = codec->dev->platform_data;  	int ret;  	u16 reg; -	if (wm8940_codec) { -		dev_err(codec->dev, "Another WM8940 is registered\n"); -		return -EINVAL; -	} - -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8940); -	codec->name = "WM8940"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8940_set_bias_level; -	codec->dai = &wm8940_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults); -	codec->reg_cache = &wm8940->reg_cache; -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); +	codec->control_data = wm8940->control_data; +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);  		return ret;  	} -	memcpy(codec->reg_cache, wm8940_reg_defaults, -	       sizeof(wm8940_reg_defaults)); -  	ret = wm8940_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n");  		return ret;  	} -	wm8940_dai.dev = codec->dev; -  	wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	ret = snd_soc_write(codec, WM8940_POWER1, 0x180); @@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940,  			return ret;  	} - -	wm8940_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); +	ret = snd_soc_add_controls(codec, wm8940_snd_controls, +			     ARRAY_SIZE(wm8940_snd_controls)); +	if (ret)  		return ret; -	} - -	ret = snd_soc_register_dai(&wm8940_dai); -	if (ret) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		snd_soc_unregister_codec(codec); +	ret = wm8940_add_widgets(codec); +	if (ret)  		return ret; -	} -	return 0; +	return ret; +;  } -static void wm8940_unregister(struct wm8940_priv *wm8940) +static int wm8940_remove(struct snd_soc_codec *codec)  { -	wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8940_dai); -	snd_soc_unregister_codec(&wm8940->codec); -	kfree(wm8940); -	wm8940_codec = NULL; +	wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -static int wm8940_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { +	.probe =	wm8940_probe, +	.remove =	wm8940_remove, +	.suspend =	wm8940_suspend, +	.resume =	wm8940_resume, +	.set_bias_level = wm8940_set_bias_level, +	.reg_cache_size = sizeof(wm8940_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8940_reg_defaults, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	int ret;  	struct wm8940_priv *wm8940; -	struct snd_soc_codec *codec; +	int ret; -	wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL); +	wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);  	if (wm8940 == NULL)  		return -ENOMEM; -	codec = &wm8940->codec; -	codec->hw_write = (hw_write_t)i2c_master_send;  	i2c_set_clientdata(i2c, wm8940); -	codec->control_data = i2c; -	codec->dev = &i2c->dev; +	wm8940->control_data = i2c; -	ret = wm8940_register(wm8940, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8940, &wm8940_dai, 1);  	if (ret < 0)  		kfree(wm8940); -  	return ret;  } -static int __devexit wm8940_i2c_remove(struct i2c_client *client) +static __devexit int wm8940_i2c_remove(struct i2c_client *client)  { -	struct wm8940_priv *wm8940 = i2c_get_clientdata(client); - -	wm8940_unregister(wm8940); - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);  static struct i2c_driver wm8940_i2c_driver = {  	.driver = { -		.name = "WM8940 I2C Codec", +		.name = "wm8940-codec",  		.owner = THIS_MODULE,  	}, -	.probe = wm8940_i2c_probe, -	.remove = __devexit_p(wm8940_i2c_remove), +	.probe =    wm8940_i2c_probe, +	.remove =   __devexit_p(wm8940_i2c_remove),  	.id_table = wm8940_i2c_id,  }; +#endif  static int __init wm8940_modinit(void)  { -	int ret; - +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8940_i2c_driver); -	if (ret) -		printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n", +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",  		       ret); +	} +#endif  	return ret;  }  module_init(wm8940_modinit);  static void __exit wm8940_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8940_i2c_driver); +#endif  }  module_exit(wm8940_exit); diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h index 8410eed3ef84..907fe192e9e0 100644 --- a/sound/soc/codecs/wm8940.h +++ b/sound/soc/codecs/wm8940.h @@ -15,8 +15,6 @@ struct wm8940_setup_data {  #define WM8940_VROI_30K 1  	unsigned int vroi:1;  }; -extern struct snd_soc_dai wm8940_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8940;  /* WM8940 register space */  #define WM8940_SOFTRESET	0x00 diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 5f025593d84d..f89ad6c9a80b 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -30,9 +30,6 @@  #include "wm8955.h" -static struct snd_soc_codec *wm8955_codec; -struct snd_soc_codec_device soc_codec_dev_wm8955; -  #define WM8955_NUM_SUPPLIES 4  static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {  	"DCVDD", @@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {  /* codec private data */  struct wm8955_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +  	u16 reg_cache[WM8955_MAX_REGISTER + 1];  	unsigned int mclk_rate; @@ -52,8 +50,6 @@ struct wm8955_priv {  	int fs;  	struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; - -	struct wm8955_pdata *pdata;  };  static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { @@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = {  	.digital_mute = wm8955_digital_mute,  }; -struct snd_soc_dai wm8955_dai = { -	.name = "WM8955", +static struct snd_soc_dai_driver wm8955_dai = { +	.name = "wm8955-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 2, @@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = {  	},  	.ops = &wm8955_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8955_dai);  #ifdef CONFIG_PM -static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8955_resume(struct platform_device *pdev) +static int wm8955_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev)  #define wm8955_resume NULL  #endif -static int wm8955_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8955_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8955_codec; -	codec = wm8955_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: %d\n", ret); -		goto pcm_err; -	} - -	wm8955_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -static int wm8955_remove(struct platform_device *pdev) +static int wm8955_probe(struct snd_soc_codec *codec)  { -	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_wm8955 = { -	.probe = 	wm8955_probe, -	.remove = 	wm8955_remove, -	.suspend = 	wm8955_suspend, -	.resume =	wm8955_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955); - -static int wm8955_register(struct wm8955_priv *wm8955, -			   enum snd_soc_control_type control) -{ -	int ret; -	struct snd_soc_codec *codec = &wm8955->codec; -	int i; - -	if (wm8955_codec) { -		dev_err(codec->dev, "Another WM8955 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8955); -	codec->name = "WM8955"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8955_set_bias_level; -	codec->dai = &wm8955_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8955_MAX_REGISTER; -	codec->reg_cache = &wm8955->reg_cache; - -	memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg)); +	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); +	struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); +	int ret, i; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) @@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955,  				 wm8955->supplies);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; +		return ret;  	}  	ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), @@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955,  		goto err_enable;  	} -	wm8955_dai.dev = codec->dev; -  	/* Change some default settings - latch VU and enable ZC */  	wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;  	wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; @@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955,  	wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;  	/* Set platform data values */ -	if (wm8955->pdata) { -		if (wm8955->pdata->out2_speaker) +	if (pdata) { +		if (pdata->out2_speaker)  			wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]  				|= WM8955_ROUT2INV; -		if (wm8955->pdata->monoin_diff) +		if (pdata->monoin_diff)  			wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]  				|= WM8955_DMEN;  	} @@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955,  	/* Bias level configuration will have done an extra enable */  	regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); -	wm8955_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_enable; -	} - -	ret = snd_soc_register_dai(&wm8955_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - +	wm8955_add_widgets(codec);  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_enable:  	regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);  err_get:  	regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); -err: -	kfree(wm8955);  	return ret;  } -static void wm8955_unregister(struct wm8955_priv *wm8955) +static int wm8955_remove(struct snd_soc_codec *codec)  { -	wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); +	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + +	wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);  	regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); -	snd_soc_unregister_dai(&wm8955_dai); -	snd_soc_unregister_codec(&wm8955->codec); -	kfree(wm8955); -	wm8955_codec = NULL; +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { +	.probe =	wm8955_probe, +	.remove =	wm8955_remove, +	.suspend =	wm8955_suspend, +	.resume =	wm8955_resume, +	.set_bias_level = wm8955_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8955_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8955_reg, +}; +  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8955_priv *wm8955; -	struct snd_soc_codec *codec; +	int ret;  	wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);  	if (wm8955 == NULL)  		return -ENOMEM; -	codec = &wm8955->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, wm8955); -	codec->control_data = i2c; -	wm8955->pdata = i2c->dev.platform_data; - -	codec->dev = &i2c->dev; -	return wm8955_register(wm8955, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8955, &wm8955_dai, 1); +	if (ret < 0) +		kfree(wm8955); +	return ret;  }  static __devexit int wm8955_i2c_remove(struct i2c_client *client)  { -	struct wm8955_priv *wm8955 = i2c_get_clientdata(client); -	wm8955_unregister(wm8955); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);  static struct i2c_driver wm8955_i2c_driver = {  	.driver = { -		.name = "wm8955", +		.name = "wm8955-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8955_i2c_probe, @@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = {  static int __init wm8955_modinit(void)  { -	int ret; +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8955_i2c_driver);  	if (ret != 0) { @@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void)  		       ret);  	}  #endif -	return 0; +	return ret;  }  module_init(wm8955_modinit); diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h index ae349c8531f6..d13fd5c5fa63 100644 --- a/sound/soc/codecs/wm8955.h +++ b/sound/soc/codecs/wm8955.h @@ -15,9 +15,6 @@  #define WM8955_CLK_MCLK 1 -extern struct snd_soc_dai wm8955_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8955; -  /*   * Register values.   */ diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3c6ee61f6c95..8d5efb333c33 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -29,8 +29,6 @@  #define AUDIO_NAME "wm8960" -struct snd_soc_codec_device soc_codec_dev_wm8960; -  /* R25 - Power 1 */  #define WM8960_VMID_MASK 0x180  #define WM8960_VREF      0x40 @@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {  struct wm8960_priv {  	u16 reg_cache[WM8960_CACHEREGNUM]; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data; +	int (*set_bias_level)(struct snd_soc_codec *, +			      enum snd_soc_bias_level level);  	struct snd_soc_dapm_widget *lout1;  	struct snd_soc_dapm_widget *rout1;  	struct snd_soc_dapm_widget *out3; @@ -507,8 +508,7 @@ static int wm8960_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;  	int i; @@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,  	return 0;  } +static int wm8960_set_bias_level(struct snd_soc_codec *codec, +				 enum snd_soc_bias_level level) +{ +	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +	return wm8960->set_bias_level(codec, level); +} +  #define WM8960_RATES SNDRV_PCM_RATE_8000_48000  #define WM8960_FORMATS \ @@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = {  	.set_pll = wm8960_set_dai_pll,  }; -struct snd_soc_dai wm8960_dai = { -	.name = "WM8960", +static struct snd_soc_dai_driver wm8960_dai = { +	.name = "wm8960-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = {  	.ops = &wm8960_dai_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8960_dai); -static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); -	codec->set_bias_level(codec, SND_SOC_BIAS_OFF); +	wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8960_resume(struct platform_device *pdev) +static int wm8960_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev)  		codec->hw_write(codec->control_data, data, 2);  	} -	codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); - +	wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0;  } -static struct snd_soc_codec *wm8960_codec; - -static int wm8960_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8960_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8960_codec; -	codec = wm8960_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8960_snd_controls, -			     ARRAY_SIZE(wm8960_snd_controls)); -	wm8960_add_widgets(codec); - -	return ret; - -pcm_err: -	return ret; -} - -/* power down chip */ -static int wm8960_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_wm8960 = { -	.probe = 	wm8960_probe, -	.remove = 	wm8960_remove, -	.suspend = 	wm8960_suspend, -	.resume =	wm8960_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); - -static int wm8960_register(struct wm8960_priv *wm8960, -			   enum snd_soc_control_type control) +static int wm8960_probe(struct snd_soc_codec *codec)  { -	struct wm8960_data *pdata = wm8960->codec.dev->platform_data; -	struct snd_soc_codec *codec = &wm8960->codec; +	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); +	struct wm8960_data *pdata = dev_get_platdata(codec->dev);  	int ret;  	u16 reg; -	if (wm8960_codec) { -		dev_err(codec->dev, "Another WM8960 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	codec->set_bias_level = wm8960_set_bias_level_out3; +	wm8960->set_bias_level = wm8960_set_bias_level_out3; +	codec->control_data = wm8960->control_data;  	if (!pdata) {  		dev_warn(codec->dev, "No platform data supplied\n"); @@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960,  		}  		if (pdata->capless) -			codec->set_bias_level = wm8960_set_bias_level_capless; +			wm8960->set_bias_level = wm8960_set_bias_level_capless;  	} -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8960); -	codec->name = "WM8960"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->dai = &wm8960_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8960_CACHEREGNUM; -	codec->reg_cache = &wm8960->reg_cache; - -	memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	ret = wm8960_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		return ret;  	} -	wm8960_dai.dev = codec->dev; - -	codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); +	wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	/* Latch the update bits */  	reg = snd_soc_read(codec, WM8960_LINVOL); @@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960,  	reg = snd_soc_read(codec, WM8960_ROUT2);  	snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); -	wm8960_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm8960_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8960_snd_controls, +				     ARRAY_SIZE(wm8960_snd_controls)); +	wm8960_add_widgets(codec);  	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8960); -	return ret;  } -static void wm8960_unregister(struct wm8960_priv *wm8960) +/* power down chip */ +static int wm8960_remove(struct snd_soc_codec *codec)  { -	wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8960_dai); -	snd_soc_unregister_codec(&wm8960->codec); -	kfree(wm8960); -	wm8960_codec = NULL; +	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +	wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { +	.probe =	wm8960_probe, +	.remove =	wm8960_remove, +	.suspend =	wm8960_suspend, +	.resume =	wm8960_resume, +	.set_bias_level = wm8960_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8960_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8960_reg, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8960_priv *wm8960; -	struct snd_soc_codec *codec; +	int ret;  	wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);  	if (wm8960 == NULL)  		return -ENOMEM; -	codec = &wm8960->codec; -  	i2c_set_clientdata(i2c, wm8960); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm8960->control_data = i2c; -	return wm8960_register(wm8960, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8960, &wm8960_dai, 1); +	if (ret < 0) +		kfree(wm8960); +	return ret;  }  static __devexit int wm8960_i2c_remove(struct i2c_client *client)  { -	struct wm8960_priv *wm8960 = i2c_get_clientdata(client); -	wm8960_unregister(wm8960); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);  static struct i2c_driver wm8960_i2c_driver = {  	.driver = { -		.name = "wm8960", +		.name = "wm8960-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8960_i2c_probe,  	.remove =   __devexit_p(wm8960_i2c_remove),  	.id_table = wm8960_i2c_id,  }; +#endif  static int __init wm8960_modinit(void)  { -	int ret; - +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8960_i2c_driver);  	if (ret != 0) {  		printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",  		       ret);  	} - +#endif  	return ret;  }  module_init(wm8960_modinit);  static void __exit wm8960_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8960_i2c_driver); +#endif  }  module_exit(wm8960_exit); -  MODULE_DESCRIPTION("ASoC WM8960 driver");  MODULE_AUTHOR("Liam Girdwood");  MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index a5ef65481b86..2d8163d7004b 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h @@ -110,7 +110,4 @@  #define WM8960_OPCLK_DIV_5_5		(4 << 0)  #define WM8960_OPCLK_DIV_6		(5 << 0) -extern struct snd_soc_dai wm8960_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8960; -  #endif diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 2549d3a297ab..fa36a62972f8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -288,7 +288,7 @@ static u16 wm8961_reg_defaults[] = {  };  struct wm8961_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	int sysclk;  	u16 reg_cache[WM8961_MAX_REGISTER];  }; @@ -940,8 +940,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = {  	.set_clkdiv = wm8961_set_clkdiv,  }; -struct snd_soc_dai wm8961_dai = { -	.name = "WM8961", +static struct snd_soc_dai_driver wm8961_dai = { +	.name = "wm8961-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -956,140 +956,23 @@ struct snd_soc_dai wm8961_dai = {  		.formats = WM8961_FORMATS,},  	.ops = &wm8961_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8961_dai); - -static struct snd_soc_codec *wm8961_codec; - -static int wm8961_probe(struct platform_device *pdev) +static int wm8961_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; - -	if (wm8961_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8961_codec; -	codec = wm8961_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8961_snd_controls, -				ARRAY_SIZE(wm8961_snd_controls)); -	snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, -				  ARRAY_SIZE(wm8961_dapm_widgets)); -	snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - -	return ret; - -pcm_err: -	return ret; -} - -static int wm8961_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; -} - -#ifdef CONFIG_PM -static int wm8961_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; - -	wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - -	return 0; -} - -static int wm8961_resume(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -	u16 *reg_cache = codec->reg_cache; -	int i; - -	for (i = 0; i < codec->reg_cache_size; i++) { -		if (reg_cache[i] == wm8961_reg_defaults[i]) -			continue; - -		if (i == WM8961_SOFTWARE_RESET) -			continue; - -		snd_soc_write(codec, i, reg_cache[i]); -	} - -	wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -	return 0; -} -#else -#define wm8961_suspend NULL -#define wm8961_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_wm8961 = { -	.probe = 	wm8961_probe, -	.remove = 	wm8961_remove, -	.suspend =	wm8961_suspend, -	.resume =	wm8961_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); - -static int wm8961_register(struct wm8961_priv *wm8961) -{ -	struct snd_soc_codec *codec = &wm8961->codec; -	int ret;  	u16 reg; -	if (wm8961_codec) { -		dev_err(codec->dev, "Another WM8961 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8961); -	codec->name = "WM8961"; -	codec->owner = THIS_MODULE; -	codec->dai = &wm8961_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); -	codec->reg_cache = &wm8961->reg_cache; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8961_set_bias_level; -	codec->volatile_register = wm8961_volatile_register; - -	memcpy(codec->reg_cache, wm8961_reg_defaults, -	       sizeof(wm8961_reg_defaults)); -  	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);  	if (ret != 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);  	if (reg != 0x1801) {  		dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); -		ret = -EINVAL; -		goto err; +		return -EINVAL;  	}  	/* This isn't volatile - readback doesn't correspond to write */ @@ -1102,7 +985,7 @@ static int wm8961_register(struct wm8961_priv *wm8961)  	ret = wm8961_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		return ret;  	}  	/* Enable class W */ @@ -1140,64 +1023,89 @@ static int wm8961_register(struct wm8961_priv *wm8961)  	wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	wm8961_dai.dev = codec->dev; +	snd_soc_add_controls(codec, wm8961_snd_controls, +				ARRAY_SIZE(wm8961_snd_controls)); +	snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, +				  ARRAY_SIZE(wm8961_dapm_widgets)); +	snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); -	wm8961_codec = codec; +	return 0; +} -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} +static int wm8961_remove(struct snd_soc_codec *codec) +{ +	wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0; +} -	ret = snd_soc_register_dai(&wm8961_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +#ifdef CONFIG_PM +static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ +	wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8961); -	return ret;  } -static void wm8961_unregister(struct wm8961_priv *wm8961) +static int wm8961_resume(struct snd_soc_codec *codec)  { -	wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8961_dai); -	snd_soc_unregister_codec(&wm8961->codec); -	kfree(wm8961); -	wm8961_codec = NULL; +	u16 *reg_cache = codec->reg_cache; +	int i; + +	for (i = 0; i < codec->driver->reg_cache_size; i++) { +		if (reg_cache[i] == wm8961_reg_defaults[i]) +			continue; + +		if (i == WM8961_SOFTWARE_RESET) +			continue; + +		snd_soc_write(codec, i, reg_cache[i]); +	} + +	wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + +	return 0;  } +#else +#define wm8961_suspend NULL +#define wm8961_resume NULL +#endif +static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { +	.probe =	wm8961_probe, +	.remove =	wm8961_remove, +	.suspend =	wm8961_suspend, +	.resume =	wm8961_resume, +	.set_bias_level = wm8961_set_bias_level, +	.reg_cache_size = sizeof(wm8961_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8961_reg_defaults, +	.volatile_register = wm8961_volatile_register, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8961_priv *wm8961; -	struct snd_soc_codec *codec; +	int ret;  	wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);  	if (wm8961 == NULL)  		return -ENOMEM; -	codec = &wm8961->codec; -  	i2c_set_clientdata(i2c, wm8961); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; -	return wm8961_register(wm8961); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8961, &wm8961_dai, 1); +	if (ret < 0) +		kfree(wm8961); +	return ret;  }  static __devexit int wm8961_i2c_remove(struct i2c_client *client)  { -	struct wm8961_priv *wm8961 = i2c_get_clientdata(client); -	wm8961_unregister(wm8961); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1209,35 +1117,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);  static struct i2c_driver wm8961_i2c_driver = {  	.driver = { -		.name = "wm8961", +		.name = "wm8961-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8961_i2c_probe,  	.remove =   __devexit_p(wm8961_i2c_remove),  	.id_table = wm8961_i2c_id,  }; +#endif  static int __init wm8961_modinit(void)  { -	int ret; - +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8961_i2c_driver);  	if (ret != 0) { -		printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", +		printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n",  		       ret);  	} - +#endif  	return ret;  }  module_init(wm8961_modinit);  static void __exit wm8961_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8961_i2c_driver); +#endif  }  module_exit(wm8961_exit); -  MODULE_DESCRIPTION("ASoC WM8961 driver");  MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");  MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h index 5513bfd720d6..1d736e5701c8 100644 --- a/sound/soc/codecs/wm8961.h +++ b/sound/soc/codecs/wm8961.h @@ -11,9 +11,6 @@  #include <sound/soc.h> -extern struct snd_soc_codec_device soc_codec_dev_wm8961; -extern struct snd_soc_dai wm8961_dai; -  #define WM8961_BCLK  1  #define WM8961_LRCLK 2 diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index a99620f335d2..63f6dbf5d070 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -30,14 +30,13 @@  #include "wm8971.h" -#define WM8971_VERSION "0.9" -  #define	WM8971_REG_COUNT		43  static struct workqueue_struct *wm8971_workq = NULL;  /* codec private data */  struct wm8971_priv { +	enum snd_soc_control_type control_type;  	unsigned int sysclk;  }; @@ -492,8 +491,7 @@ static int wm8971_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;  	u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; @@ -573,8 +571,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = {  	.set_sysclk	= wm8971_set_dai_sysclk,  }; -struct snd_soc_dai wm8971_dai = { -	.name = "WM8971", +static struct snd_soc_dai_driver wm8971_dai = { +	.name = "wm8971-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -589,7 +587,6 @@ struct snd_soc_dai wm8971_dai = {  		.formats = WM8971_FORMATS,},  	.ops = &wm8971_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8971_dai);  static void wm8971_work(struct work_struct *work)  { @@ -598,19 +595,14 @@ static void wm8971_work(struct work_struct *work)  	wm8971_set_bias_level(codec, codec->bias_level);  } -static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8971_resume(struct platform_device *pdev) +static int wm8971_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -639,37 +631,24 @@ static int wm8971_resume(struct platform_device *pdev)  	return 0;  } -static int wm8971_init(struct snd_soc_device *socdev, -		       enum snd_soc_control_type control) +static int wm8971_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; -	int reg, ret = 0; - -	codec->name = "WM8971"; -	codec->owner = THIS_MODULE; -	codec->set_bias_level = wm8971_set_bias_level; -	codec->dai = &wm8971_dai; -	codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); -	codec->num_dai = 1; -	codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL); - -	if (codec->reg_cache == NULL) -		return -ENOMEM; +	struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); +	int ret = 0; +	u16 reg; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);  	if (ret < 0) {  		printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	} -	wm8971_reset(codec); +	INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); +	wm8971_workq = create_workqueue("wm8971"); +	if (wm8971_workq == NULL) +		return -ENOMEM; -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8971: failed to create pcms\n"); -		goto err; -	} +	wm8971_reset(codec);  	/* charge output caps - set vmid to 5k for quick power up */  	reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; @@ -704,40 +683,54 @@ static int wm8971_init(struct snd_soc_device *socdev,  	wm8971_add_widgets(codec);  	return ret; - -err: -	kfree(codec->reg_cache); -	return ret;  } -/* If the i2c layer weren't so broken, we could pass this kind of data -   around */ -static struct snd_soc_device *wm8971_socdev; -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) +/* power down chip */ +static int wm8971_remove(struct snd_soc_codec *codec) +{ +	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); + +	if (wm8971_workq) +		destroy_workqueue(wm8971_workq); +	return 0; +} -static int wm8971_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { +	.probe =	wm8971_probe, +	.remove =	wm8971_remove, +	.suspend =	wm8971_suspend, +	.resume =	wm8971_resume, +	.set_bias_level = wm8971_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8971_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8971_reg, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = wm8971_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8971_priv *wm8971;  	int ret; -	i2c_set_clientdata(i2c, codec); +	wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); +	if (wm8971 == NULL) +		return -ENOMEM; -	codec->control_data = i2c; +	i2c_set_clientdata(i2c, wm8971); -	ret = wm8971_init(socdev, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8971, &wm8971_dai, 1);  	if (ret < 0) -		pr_err("failed to initialise WM8971\n"); - +		kfree(wm8971);  	return ret;  } -static int wm8971_i2c_remove(struct i2c_client *client) +static __devexit int wm8971_i2c_remove(struct i2c_client *client)  { -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -749,148 +742,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);  static struct i2c_driver wm8971_i2c_driver = {  	.driver = { -		.name = "WM8971 I2C Codec", +		.name = "wm8971-codec",  		.owner = THIS_MODULE,  	}, -	.probe    = wm8971_i2c_probe, -	.remove   = wm8971_i2c_remove, +	.probe =    wm8971_i2c_probe, +	.remove =   __devexit_p(wm8971_i2c_remove),  	.id_table = wm8971_i2c_id,  }; - -static int wm8971_add_i2c_device(struct platform_device *pdev, -				 const struct wm8971_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&wm8971_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "wm8971", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -			setup->i2c_bus); -		goto err_driver; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -			(unsigned int)info.addr); -		goto err_driver; -	} - -	return 0; - -err_driver: -	i2c_del_driver(&wm8971_i2c_driver); -	return -ENODEV; -} -  #endif -static int wm8971_probe(struct platform_device *pdev) +static int __init wm8971_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct wm8971_setup_data *setup; -	struct snd_soc_codec *codec; -	struct wm8971_priv *wm8971;  	int ret = 0; - -	pr_info("WM8971 Audio Codec %s", WM8971_VERSION); - -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; - -	wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); -	if (wm8971 == NULL) { -		kfree(codec); -		return -ENOMEM; -	} - -	snd_soc_codec_set_drvdata(codec, wm8971); -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	wm8971_socdev = socdev; - -	INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); -	wm8971_workq = create_workqueue("wm8971"); -	if (wm8971_workq == NULL) { -		kfree(snd_soc_codec_get_drvdata(codec)); -		kfree(codec); -		return -ENOMEM; -	} - -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		ret = wm8971_add_i2c_device(pdev, setup); -	} -#endif -	/* Add other interfaces here */ - +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8971_i2c_driver);  	if (ret != 0) { -		destroy_workqueue(wm8971_workq); -		kfree(snd_soc_codec_get_drvdata(codec)); -		kfree(codec); +		printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", +		       ret);  	} - -	return ret; -} - -/* power down chip */ -static int wm8971_remove(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); -	if (wm8971_workq) -		destroy_workqueue(wm8971_workq); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) -	i2c_unregister_device(codec->control_data); -	i2c_del_driver(&wm8971_i2c_driver);  #endif -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8971 = { -	.probe = 	wm8971_probe, -	.remove = 	wm8971_remove, -	.suspend = 	wm8971_suspend, -	.resume =	wm8971_resume, -}; - -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); - -static int __init wm8971_modinit(void) -{ -	return snd_soc_register_dai(&wm8971_dai); +	return ret;  }  module_init(wm8971_modinit);  static void __exit wm8971_exit(void)  { -	snd_soc_unregister_dai(&wm8971_dai); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	i2c_del_driver(&wm8971_i2c_driver); +#endif  }  module_exit(wm8971_exit); diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h index ef4f08f9f344..f31c38fddfc4 100644 --- a/sound/soc/codecs/wm8971.h +++ b/sound/soc/codecs/wm8971.h @@ -53,12 +53,4 @@  #define WM8971_SYSCLK	0 -struct wm8971_setup_data { -	int i2c_bus; -	unsigned short i2c_address; -}; - -extern struct snd_soc_dai wm8971_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8971; -  #endif diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 1468fe10cbbe..e61728b7339f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -51,12 +51,10 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {  #define WM8974_POWER1_BUFIOEN 0x04  struct wm8974_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	u16 reg_cache[WM8974_CACHEREGNUM];  }; -static struct snd_soc_codec *wm8974_codec; -  #define wm8974_reset(c)	snd_soc_write(c, WM8974_RESET, 0)  static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; @@ -566,8 +564,8 @@ static struct snd_soc_dai_ops wm8974_ops = {  	.set_pll = wm8974_set_dai_pll,  }; -struct snd_soc_dai wm8974_dai = { -	.name = "WM8974 HiFi", +static struct snd_soc_dai_driver wm8974_dai = { +	.name = "wm8974-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -583,21 +581,15 @@ struct snd_soc_dai wm8974_dai = {  	.ops = &wm8974_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8974_dai); -static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8974_resume(struct platform_device *pdev) +static int wm8974_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -613,156 +605,73 @@ static int wm8974_resume(struct platform_device *pdev)  	return 0;  } -static int wm8974_probe(struct platform_device *pdev) +static int wm8974_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; -	if (wm8974_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); +	if (ret < 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm8974_codec; -	codec = wm8974_codec; - -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = wm8974_reset(codec);  	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto pcm_err; +		dev_err(codec->dev, "Failed to issue reset\n"); +		return ret;  	} +	wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	snd_soc_add_controls(codec, wm8974_snd_controls,  			     ARRAY_SIZE(wm8974_snd_controls));  	wm8974_add_widgets(codec);  	return ret; - -pcm_err: -	return ret;  }  /* power down chip */ -static int wm8974_remove(struct platform_device *pdev) +static int wm8974_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - +	wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm8974 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {  	.probe = 	wm8974_probe,  	.remove = 	wm8974_remove,  	.suspend = 	wm8974_suspend,  	.resume =	wm8974_resume, +	.set_bias_level = wm8974_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8974_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8974_reg,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974); - -static __devinit int wm8974_register(struct wm8974_priv *wm8974) -{ -	int ret; -	struct snd_soc_codec *codec = &wm8974->codec; - -	if (wm8974_codec) { -		dev_err(codec->dev, "Another WM8974 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8974); -	codec->name = "WM8974"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8974_set_bias_level; -	codec->dai = &wm8974_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8974_CACHEREGNUM; -	codec->reg_cache = &wm8974->reg_cache; - -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} - -	memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); - -	ret = wm8974_reset(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; -	} - -	wm8974_dai.dev = codec->dev; - -	wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -	wm8974_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm8974_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8974); -	return ret; -} - -static __devexit void wm8974_unregister(struct wm8974_priv *wm8974) -{ -	wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8974_dai); -	snd_soc_unregister_codec(&wm8974->codec); -	kfree(wm8974); -	wm8974_codec = NULL; -} +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm8974_priv *wm8974; -	struct snd_soc_codec *codec; +	int ret;  	wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);  	if (wm8974 == NULL)  		return -ENOMEM; -	codec = &wm8974->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, wm8974); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; -	return wm8974_register(wm8974); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8974, &wm8974_dai, 1); +	if (ret < 0) +		kfree(wm8974); +	return ret;  }  static __devexit int wm8974_i2c_remove(struct i2c_client *client)  { -	struct wm8974_priv *wm8974 = i2c_get_clientdata(client); -	wm8974_unregister(wm8974); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -774,23 +683,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);  static struct i2c_driver wm8974_i2c_driver = {  	.driver = { -		.name = "WM8974", +		.name = "wm8974-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8974_i2c_probe,  	.remove =   __devexit_p(wm8974_i2c_remove),  	.id_table = wm8974_i2c_id,  }; +#endif  static int __init wm8974_modinit(void)  { -	return i2c_add_driver(&wm8974_i2c_driver); +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8974_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", +		       ret); +	} +#endif +	return ret;  }  module_init(wm8974_modinit);  static void __exit wm8974_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8974_i2c_driver); +#endif  }  module_exit(wm8974_exit); diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 896a7f0f3fc4..3c94e7bb55a6 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h @@ -83,7 +83,4 @@  #define WM8974_MCLKDIV_8	(6 << 5)  #define WM8974_MCLKDIV_12	(7 << 5) -extern struct snd_soc_dai wm8974_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8974; -  #endif diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8a1ad778e7e3..676a4306cc87 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -31,8 +31,6 @@  #include "wm8978.h" -static struct snd_soc_codec *wm8978_codec; -  /* wm8978 register cache. Note that register 0 is not included in the cache. */  static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {  	0x0000, 0x0000, 0x0000, 0x0000,	/* 0x00...0x03 */ @@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {  /* codec private data */  struct wm8978_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	unsigned int f_pllout;  	unsigned int f_mclk;  	unsigned int f_256fs; @@ -374,8 +373,8 @@ struct wm8978_pll_div {  #define FIXED_PLL_SIZE (1 << 24) -static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, -			unsigned int source) +static void pll_factors(struct snd_soc_codec *codec, +		struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source)  {  	u64 k_part;  	unsigned int k, n_div, n_mod; @@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,  	}  	if (n_div < 6 || n_div > 12) -		dev_warn(wm8978_codec->dev, +		dev_warn(codec->dev,  			 "WM8978 N value exceeds recommended range! N = %u\n",  			 n_div); @@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)  	dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__,  		wm8978->f_mclk, wm8978->f_pllout); -	pll_factors(&pll_div, f2, wm8978->f_mclk); +	pll_factors(codec, &pll_div, f2, wm8978->f_mclk);  	dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n",  		__func__, pll_div.n, pll_div.k, pll_div.div2); @@ -690,8 +689,7 @@ static int wm8978_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);  	/* Word length mask = 0x60 */  	u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; @@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = {  };  /* Also supports 12kHz */ -struct snd_soc_dai wm8978_dai = { -	.name = "WM8978 HiFi", -	.id = 1, +static struct snd_soc_dai_driver wm8978_dai = { +	.name = "wm8978-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = {  	},  	.ops = &wm8978_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8978_dai); -static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);  	/* Also switch PLL off */  	snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); @@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)  	return 0;  } -static int wm8978_resume(struct platform_device *pdev) +static int wm8978_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);  	int i;  	u16 *cache = codec->reg_cache; @@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev)  	return 0;  } -static int wm8978_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8978_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8978_codec; -	codec = wm8978_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8978_snd_controls, -			     ARRAY_SIZE(wm8978_snd_controls)); -	wm8978_add_widgets(codec); - -pcm_err: -	return ret; -} - -/* power down chip */ -static int wm8978_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_wm8978 = { -	.probe		= wm8978_probe, -	.remove		= wm8978_remove, -	.suspend	= wm8978_suspend, -	.resume		= wm8978_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978); -  /*   * These registers contain an "update" bit - bit 8. This means, for example,   * that one can write new DAC digital volume for both channels, but only when @@ -1000,44 +943,23 @@ static const int update_reg[] = {  	WM8978_ROUT2_SPK_CONTROL,  }; -static __devinit int wm8978_register(struct wm8978_priv *wm8978) +static int wm8978_probe(struct snd_soc_codec *codec)  { -	int ret, i; -	struct snd_soc_codec *codec = &wm8978->codec; - -	if (wm8978_codec) { -		dev_err(codec->dev, "Another WM8978 is registered\n"); -		return -EINVAL; -	} +	struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); +	int ret = 0, i;  	/*  	 * Set default system clock to PLL, it is more precise, this is also the  	 * default hardware setting  	 */  	wm8978->sysclk = WM8978_PLL; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8978); -	codec->name = "WM8978"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8978_set_bias_level; -	codec->dai = &wm8978_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = WM8978_CACHEREGNUM; -	codec->reg_cache = &wm8978->reg_cache; - +	codec->control_data = wm8978->control_data;  	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	} -	memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg)); -  	/*  	 * Set the update bit in all registers, that have one. This way all  	 * writes to those registers will also cause the update bit to be @@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978)  	ret = snd_soc_write(codec, WM8978_RESET, 0);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		return ret;  	} -	wm8978_dai.dev = codec->dev; -  	wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	wm8978_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm8978_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8978_snd_controls, +			     ARRAY_SIZE(wm8978_snd_controls)); +	wm8978_add_widgets(codec);  	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	return ret;  } -static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) +/* power down chip */ +static int wm8978_remove(struct snd_soc_codec *codec)  { -	wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8978_dai); -	snd_soc_unregister_codec(&wm8978->codec); -	wm8978_codec = NULL; +	wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { +	.probe =	wm8978_probe, +	.remove =	wm8978_remove, +	.suspend =	wm8978_suspend, +	.resume =	wm8978_resume, +	.set_bias_level = wm8978_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8978_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8978_reg, +}; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  { -	int ret;  	struct wm8978_priv *wm8978; -	struct snd_soc_codec *codec; +	int ret;  	wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);  	if (wm8978 == NULL)  		return -ENOMEM; -	codec = &wm8978->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -  	i2c_set_clientdata(i2c, wm8978); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm8978->control_data = i2c; -	ret = wm8978_register(wm8978); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8978, &wm8978_dai, 1);  	if (ret < 0)  		kfree(wm8978); -  	return ret;  }  static __devexit int wm8978_i2c_remove(struct i2c_client *client)  { -	struct wm8978_priv *wm8978 = i2c_get_clientdata(client); -	wm8978_unregister(wm8978); -	kfree(wm8978); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);  static struct i2c_driver wm8978_i2c_driver = {  	.driver = { -		.name = "WM8978", +		.name = "WM8978-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8978_i2c_probe,  	.remove =   __devexit_p(wm8978_i2c_remove),  	.id_table = wm8978_i2c_id,  }; +#endif  static int __init wm8978_modinit(void)  { -	return i2c_add_driver(&wm8978_i2c_driver); +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +	ret = i2c_add_driver(&wm8978_i2c_driver); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", +		       ret); +	} +#endif +	return ret;  }  module_init(wm8978_modinit);  static void __exit wm8978_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8978_i2c_driver); +#endif  }  module_exit(wm8978_exit); diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h index 56ec83270917..c75525b7f154 100644 --- a/sound/soc/codecs/wm8978.h +++ b/sound/soc/codecs/wm8978.h @@ -80,7 +80,4 @@ enum wm8978_sysclk_src {  	WM8978_MCLK  }; -extern struct snd_soc_dai wm8978_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8978; -  #endif	/* __WM8978_H__ */ diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 19ad590ca0b3..d070a58e4f8e 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -52,7 +52,7 @@ static const u16 wm8988_reg[] = {  /* codec private data */  struct wm8988_priv {  	unsigned int sysclk; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	struct snd_pcm_hw_constraint_list *sysclk_constraints;  	u16 reg_cache[WM8988_NUM_REG];  }; @@ -608,8 +608,7 @@ static int wm8988_pcm_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);  	u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;  	u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; @@ -711,8 +710,8 @@ static struct snd_soc_dai_ops wm8988_ops = {  	.digital_mute = wm8988_mute,  }; -struct snd_soc_dai wm8988_dai = { -	.name = "WM8988", +static struct snd_soc_dai_driver wm8988_dai = { +	.name = "wm8988-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -730,21 +729,15 @@ struct snd_soc_dai wm8988_dai = {  	.ops = &wm8988_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8988_dai); -static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8988_resume(struct platform_device *pdev) +static int wm8988_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -763,99 +756,22 @@ static int wm8988_resume(struct platform_device *pdev)  	return 0;  } -static struct snd_soc_codec *wm8988_codec; - -static int wm8988_probe(struct platform_device *pdev) +static int wm8988_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);  	int ret = 0; - -	if (wm8988_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8988_codec; -	codec = wm8988_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: %d\n", ret); -		goto pcm_err; -	} - -	snd_soc_add_controls(codec, wm8988_snd_controls, -				ARRAY_SIZE(wm8988_snd_controls)); -	snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, -				  ARRAY_SIZE(wm8988_dapm_widgets)); -	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - -	return ret; - -pcm_err: -	return ret; -} - -static int wm8988_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_wm8988 = { -	.probe = 	wm8988_probe, -	.remove = 	wm8988_remove, -	.suspend = 	wm8988_suspend, -	.resume =	wm8988_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); - -static int wm8988_register(struct wm8988_priv *wm8988, -			   enum snd_soc_control_type control) -{ -	struct snd_soc_codec *codec = &wm8988->codec; -	int ret;  	u16 reg; -	if (wm8988_codec) { -		dev_err(codec->dev, "Another WM8988 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm8988); -	codec->name = "WM8988"; -	codec->owner = THIS_MODULE; -	codec->dai = &wm8988_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); -	codec->reg_cache = &wm8988->reg_cache; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8988_set_bias_level; - -	memcpy(codec->reg_cache, wm8988_reg, -	       sizeof(wm8988_reg)); - -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); +	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; +		return ret;  	}  	ret = wm8988_reset(codec);  	if (ret < 0) {  		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; +		return ret;  	}  	/* set the update bits (we always update left then right) */ @@ -870,139 +786,133 @@ static int wm8988_register(struct wm8988_priv *wm8988,  	reg = snd_soc_read(codec, WM8988_RINVOL);  	snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); -	wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); - -	wm8988_dai.dev = codec->dev; - -	wm8988_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} +	wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	ret = snd_soc_register_dai(&wm8988_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} +	snd_soc_add_controls(codec, wm8988_snd_controls, +				ARRAY_SIZE(wm8988_snd_controls)); +	snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, +				  ARRAY_SIZE(wm8988_dapm_widgets)); +	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));  	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm8988); -	return ret;  } -static void wm8988_unregister(struct wm8988_priv *wm8988) +static int wm8988_remove(struct snd_soc_codec *codec)  { -	wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm8988_dai); -	snd_soc_unregister_codec(&wm8988->codec); -	kfree(wm8988); -	wm8988_codec = NULL; +	wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int wm8988_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { +	.probe =	wm8988_probe, +	.remove =	wm8988_remove, +	.suspend =	wm8988_suspend, +	.resume =	wm8988_resume, +	.set_bias_level = wm8988_set_bias_level, +	.reg_cache_size = sizeof(wm8988_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8988_reg, +}; + +#if defined(CONFIG_SPI_MASTER) +static int __devinit wm8988_spi_probe(struct spi_device *spi)  {  	struct wm8988_priv *wm8988; -	struct snd_soc_codec *codec; +	int ret;  	wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);  	if (wm8988 == NULL)  		return -ENOMEM; -	codec = &wm8988->codec; - -	i2c_set_clientdata(i2c, wm8988); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm8988->control_type = SND_SOC_SPI; +	spi_set_drvdata(spi, wm8988); -	return wm8988_register(wm8988, SND_SOC_I2C); +	ret = snd_soc_register_codec(&spi->dev, +			&soc_codec_dev_wm8988, &wm8988_dai, 1); +	if (ret < 0) +		kfree(wm8988); +	return ret;  } -static int wm8988_i2c_remove(struct i2c_client *client) +static int __devexit wm8988_spi_remove(struct spi_device *spi)  { -	struct wm8988_priv *wm8988 = i2c_get_clientdata(client); -	wm8988_unregister(wm8988); +	snd_soc_unregister_codec(&spi->dev); +	kfree(spi_get_drvdata(spi));  	return 0;  } -static const struct i2c_device_id wm8988_i2c_id[] = { -	{ "wm8988", 0 }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); - -static struct i2c_driver wm8988_i2c_driver = { +static struct spi_driver wm8988_spi_driver = {  	.driver = { -		.name = "WM8988", -		.owner = THIS_MODULE, +		.name	= "wm8988-codec", +		.bus	= &spi_bus_type, +		.owner	= THIS_MODULE,  	}, -	.probe = wm8988_i2c_probe, -	.remove = wm8988_i2c_remove, -	.id_table = wm8988_i2c_id, +	.probe		= wm8988_spi_probe, +	.remove		= __devexit_p(wm8988_spi_remove),  }; -#endif +#endif /* CONFIG_SPI_MASTER */ -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8988_spi_probe(struct spi_device *spi) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  {  	struct wm8988_priv *wm8988; -	struct snd_soc_codec *codec; +	int ret;  	wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);  	if (wm8988 == NULL)  		return -ENOMEM; -	codec = &wm8988->codec; -	codec->control_data = spi; -	codec->dev = &spi->dev; - -	dev_set_drvdata(&spi->dev, wm8988); +	i2c_set_clientdata(i2c, wm8988); +	wm8988->control_type = SND_SOC_I2C; -	return wm8988_register(wm8988, SND_SOC_SPI); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8988, &wm8988_dai, 1); +	if (ret < 0) +		kfree(wm8988); +	return ret;  } -static int __devexit wm8988_spi_remove(struct spi_device *spi) +static __devexit int wm8988_i2c_remove(struct i2c_client *client)  { -	struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev); - -	wm8988_unregister(wm8988); - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } -static struct spi_driver wm8988_spi_driver = { +static const struct i2c_device_id wm8988_i2c_id[] = { +	{ "wm8988", 0 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); + +static struct i2c_driver wm8988_i2c_driver = {  	.driver = { -		.name	= "wm8988", -		.bus	= &spi_bus_type, -		.owner	= THIS_MODULE, +		.name = "wm8988-codec", +		.owner = THIS_MODULE,  	}, -	.probe		= wm8988_spi_probe, -	.remove		= __devexit_p(wm8988_spi_remove), +	.probe =    wm8988_i2c_probe, +	.remove =   __devexit_p(wm8988_i2c_remove), +	.id_table = wm8988_i2c_id,  };  #endif  static int __init wm8988_modinit(void)  { -	int ret; - +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8988_i2c_driver); -	if (ret != 0) -		pr_err("WM8988: Unable to register I2C driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", +		       ret); +	}  #endif  #if defined(CONFIG_SPI_MASTER)  	ret = spi_register_driver(&wm8988_spi_driver); -	if (ret != 0) -		pr_err("WM8988: Unable to register SPI driver: %d\n", ret); +	if (ret != 0) { +		printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n", +		       ret); +	}  #endif  	return ret;  } diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h index 4552d37fdd41..5c04024e5f9f 100644 --- a/sound/soc/codecs/wm8988.h +++ b/sound/soc/codecs/wm8988.h @@ -54,7 +54,4 @@  #define WM8988_SYSCLK	0 -extern struct snd_soc_dai wm8988_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8988; -  #endif diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd8d909788c1..0ffecbd1e33b 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -32,6 +32,7 @@  /* codec private data */  struct wm8990_priv { +	enum snd_soc_control_type control_type;  	unsigned int sysclk;  	unsigned int pcmclk;  }; @@ -1114,8 +1115,7 @@ static int wm8990_hw_params(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; +	struct snd_soc_codec *codec = rtd->codec;  	u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);  	audio1 &= ~WM8990_AIF_WL_MASK; @@ -1293,10 +1293,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = {  	.set_sysclk	= wm8990_set_dai_sysclk,  }; -struct snd_soc_dai wm8990_dai = { +static struct snd_soc_dai_driver wm8990_dai = {  /* ADC/DAC on primary */ -	.name = "WM8990 ADC/DAC Primary", -	.id = 1, +	.name = "wm8990-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -1311,21 +1310,15 @@ struct snd_soc_dai wm8990_dai = {  		.formats = WM8990_FORMATS,},  	.ops = &wm8990_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm8990_dai); -static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm8990_resume(struct platform_device *pdev) +static int wm8990_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i;  	u8 data[2];  	u16 *cache = codec->reg_cache; @@ -1347,38 +1340,19 @@ static int wm8990_resume(struct platform_device *pdev)   * initialise the WM8990 driver   * register the mixer and dsp interfaces with the kernel   */ -static int wm8990_init(struct snd_soc_device *socdev) +static int wm8990_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; +	int ret;  	u16 reg; -	int ret = 0; - -	codec->name = "WM8990"; -	codec->owner = THIS_MODULE; -	codec->set_bias_level = wm8990_set_bias_level; -	codec->dai = &wm8990_dai; -	codec->num_dai = 2; -	codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); -	codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); - -	if (codec->reg_cache == NULL) -		return -ENOMEM;  	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);  	if (ret < 0) {  		printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); -		goto pcm_err; +		return ret;  	}  	wm8990_reset(codec); -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		printk(KERN_ERR "wm8990: failed to create pcms\n"); -		goto pcm_err; -	} -  	/* charge output caps */  	codec->bias_level = SND_SOC_BIAS_OFF;  	wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1400,47 +1374,51 @@ static int wm8990_init(struct snd_soc_device *socdev)  				ARRAY_SIZE(wm8990_snd_controls));  	wm8990_add_widgets(codec); -	return ret; +	return 0; +} -pcm_err: -	kfree(codec->reg_cache); -	return ret; +/* power down chip */ +static int wm8990_remove(struct snd_soc_codec *codec) +{ +	wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); +	return 0;  } -/* If the i2c layer weren't so broken, we could pass this kind of data -   around */ -static struct snd_soc_device *wm8990_socdev; +static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { +	.probe =	wm8990_probe, +	.remove =	wm8990_remove, +	.suspend =	wm8990_suspend, +	.resume =	wm8990_resume, +	.set_bias_level = wm8990_set_bias_level, +	.reg_cache_size = ARRAY_SIZE(wm8990_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8990_reg, +};  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM891 2 wire address is determined by GPIO5 - * state during powerup. - *    low  = 0x34 - *    high = 0x36 - */ - -static int wm8990_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  { -	struct snd_soc_device *socdev = wm8990_socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct wm8990_priv *wm8990;  	int ret; -	i2c_set_clientdata(i2c, codec); -	codec->control_data = i2c; +	wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); +	if (wm8990 == NULL) +		return -ENOMEM; -	ret = wm8990_init(socdev); -	if (ret < 0) -		pr_err("failed to initialise WM8990\n"); +	i2c_set_clientdata(i2c, wm8990); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8990, &wm8990_dai, 1); +	if (ret < 0) +		kfree(wm8990);  	return ret;  } -static int wm8990_i2c_remove(struct i2c_client *client) +static __devexit int wm8990_i2c_remove(struct i2c_client *client)  { -	struct snd_soc_codec *codec = i2c_get_clientdata(client); -	kfree(codec->reg_cache); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1452,134 +1430,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);  static struct i2c_driver wm8990_i2c_driver = {  	.driver = { -		.name = "WM8990 I2C Codec", +		.name = "wm8990-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm8990_i2c_probe, -	.remove =   wm8990_i2c_remove, +	.remove =   __devexit_p(wm8990_i2c_remove),  	.id_table = wm8990_i2c_id,  }; - -static int wm8990_add_i2c_device(struct platform_device *pdev, -				 const struct wm8990_setup_data *setup) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; -	int ret; - -	ret = i2c_add_driver(&wm8990_i2c_driver); -	if (ret != 0) { -		dev_err(&pdev->dev, "can't add i2c driver\n"); -		return ret; -	} - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = setup->i2c_address; -	strlcpy(info.type, "wm8990", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(setup->i2c_bus); -	if (!adapter) { -		dev_err(&pdev->dev, "can't get i2c adapter %d\n", -			setup->i2c_bus); -		goto err_driver; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", -			(unsigned int)info.addr); -		goto err_driver; -	} - -	return 0; - -err_driver: -	i2c_del_driver(&wm8990_i2c_driver); -	return -ENODEV; -}  #endif -static int wm8990_probe(struct platform_device *pdev) +static int __init wm8990_modinit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct wm8990_setup_data *setup; -	struct snd_soc_codec *codec; -	struct wm8990_priv *wm8990; -	int ret; - -	setup = socdev->codec_data; -	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); -	if (codec == NULL) -		return -ENOMEM; - -	wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); -	if (wm8990 == NULL) { -		kfree(codec); -		return -ENOMEM; -	} - -	snd_soc_codec_set_drvdata(codec, wm8990); -	socdev->card->codec = codec; -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -	wm8990_socdev = socdev; - -	ret = -ENODEV; - +	int ret = 0;  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	if (setup->i2c_address) { -		codec->hw_write = (hw_write_t)i2c_master_send; -		ret = wm8990_add_i2c_device(pdev, setup); -	} -#endif - +	ret = i2c_add_driver(&wm8990_i2c_driver);  	if (ret != 0) { -		kfree(snd_soc_codec_get_drvdata(codec)); -		kfree(codec); +		printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", +		       ret);  	} +#endif  	return ret;  } +module_init(wm8990_modinit); -/* power down chip */ -static int wm8990_remove(struct platform_device *pdev) +static void __exit wm8990_exit(void)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec->control_data) -		wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev);  #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -	i2c_unregister_device(codec->control_data);  	i2c_del_driver(&wm8990_i2c_driver);  #endif -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec); - -	return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8990 = { -	.probe =	wm8990_probe, -	.remove =	wm8990_remove, -	.suspend =	wm8990_suspend, -	.resume =	wm8990_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); - -static int __init wm8990_modinit(void) -{ -	return snd_soc_register_dai(&wm8990_dai); -} -module_init(wm8990_modinit); - -static void __exit wm8990_exit(void) -{ -	snd_soc_unregister_dai(&wm8990_dai);  }  module_exit(wm8990_exit); diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 7114ddc88b4b..77c98a4bfe9c 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h @@ -826,18 +826,10 @@  #define WM8990_INMIXR_PWR_BIT			2  #define WM8990_AINRMUX_PWR_BIT			3 -struct wm8990_setup_data { -	unsigned i2c_bus; -	unsigned short i2c_address; -}; -  #define WM8990_MCLK_DIV 0  #define WM8990_DACCLK_DIV 1  #define WM8990_ADCCLK_DIV 2  #define WM8990_BCLK_DIV 3 -extern struct snd_soc_dai wm8990_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8990; -  #endif	/* __WM8990REGISTERDEFS_H__ */  /*------------------------------ END OF FILE ---------------------------------*/ diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d8d300c6175f..a3fd6b935804 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -229,7 +229,7 @@ struct wm8993_priv {  	u16 reg_cache[WM8993_REGISTER_COUNT];  	struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];  	struct wm8993_platform_data pdata; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type;  	int master;  	int sysclk_source;  	int tdm_slots; @@ -367,10 +367,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,  	return 0;  } -static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, +static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,  			  unsigned int Fref, unsigned int Fout)  { -	struct snd_soc_codec *codec = dai->codec;  	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);  	u16 reg1, reg4, reg5;  	struct _fll_div fll_div; @@ -456,6 +455,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,  	return 0;  } +static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, +			  unsigned int Fref, unsigned int Fout) +{ +	return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); +} +  static int configure_clock(struct snd_soc_codec *codec)  {  	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); @@ -1394,8 +1399,8 @@ static struct snd_soc_dai_ops wm8993_ops = {  			SNDRV_PCM_FMTBIT_S24_LE |\  			SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai wm8993_dai = { -	.name = "WM8993", +static struct snd_soc_dai_driver wm8993_dai = { +	.name = "wm8993-hifi",  	.playback = {  		.stream_name = "Playback",  		.channels_min = 1, @@ -1413,32 +1418,81 @@ struct snd_soc_dai wm8993_dai = {  	.ops = &wm8993_ops,  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(wm8993_dai); - -static struct snd_soc_codec *wm8993_codec; -static int wm8993_probe(struct platform_device *pdev) +static int wm8993_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct wm8993_priv *wm8993; -	int ret = 0; +	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); +	int ret, i, val; + +	wm8993->hubs_data.hp_startup_mode = 1; +	wm8993->hubs_data.dcs_codes = -2; + +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret; +	} + +	for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) +		wm8993->supplies[i].supply = wm8993_supply_names[i]; -	if (!wm8993_codec) { -		dev_err(&pdev->dev, "I2C device not yet probed\n"); -		goto err; +	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), +				 wm8993->supplies); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm8993_codec; -	codec = wm8993_codec; -	wm8993 = snd_soc_codec_get_drvdata(codec); +	ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), +				    wm8993->supplies); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); +		goto err_get; +	} -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms\n"); -		goto err; +	val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); +	if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { +		dev_err(codec->dev, "Invalid ID register value %x\n", val); +		ret = -EINVAL; +		goto err_enable;  	} +	ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); +	if (ret != 0) +		goto err_enable; + +	codec->cache_only = 1; + +	/* By default we're using the output mixers */ +	wm8993->class_w_users = 2; + +	/* Latch volume update bits and default ZC on */ +	snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, +			    WM8993_DAC_VU, WM8993_DAC_VU); +	snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, +			    WM8993_ADC_VU, WM8993_ADC_VU); + +	/* Manualy manage the HPOUT sequencing for independent stereo +	 * control. */ +	snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, +			    WM8993_HPOUT1_AUTO_PU, 0); + +	/* Use automatic clock configuration */ +	snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); + +	wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, +				      wm8993->pdata.lineout2_diff, +				      wm8993->pdata.lineout1fb, +				      wm8993->pdata.lineout2fb, +				      wm8993->pdata.jd_scthr, +				      wm8993->pdata.jd_thr, +				      wm8993->pdata.micbias1_lvl, +				      wm8993->pdata.micbias2_lvl); + +	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +	if (ret != 0) +		goto err_enable; +  	snd_soc_add_controls(codec, wm8993_snd_controls,  			     ARRAY_SIZE(wm8993_snd_controls));  	if (wm8993->pdata.num_retune_configs != 0) { @@ -1457,36 +1511,36 @@ static int wm8993_probe(struct platform_device *pdev)  	wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,  				    wm8993->pdata.lineout2_diff); -	return ret; +	return 0; -err: +err_enable: +	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); +err_get: +	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);  	return ret;  } -static int wm8993_remove(struct platform_device *pdev) +static int wm8993_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); +	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); +	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);  	return 0;  }  #ifdef CONFIG_PM -static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);  	int fll_fout = wm8993->fll_fout;  	int fll_fref  = wm8993->fll_fref;  	int ret;  	/* Stop the FLL in an orderly fashion */ -	ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); +	ret = _wm8993_set_fll(codec, 0, 0, 0, 0);  	if (ret != 0) { -		dev_err(&pdev->dev, "Failed to stop FLL\n"); +		dev_err(codec->dev, "Failed to stop FLL\n");  		return ret;  	} @@ -1498,10 +1552,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)  	return 0;  } -static int wm8993_resume(struct platform_device *pdev) +static int wm8993_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);  	int ret; @@ -1515,7 +1567,7 @@ static int wm8993_resume(struct platform_device *pdev)  		wm8993->fll_fref = 0;  		wm8993->fll_fout = 0; -		ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, +		ret = _wm8993_set_fll(codec, 0, wm8993->fll_src,  				     fll_fref, fll_fout);  		if (ret != 0)  			dev_err(codec->dev, "Failed to restart FLL\n"); @@ -1528,162 +1580,42 @@ static int wm8993_resume(struct platform_device *pdev)  #define wm8993_resume NULL  #endif -struct snd_soc_codec_device soc_codec_dev_wm8993 = { +static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {  	.probe = 	wm8993_probe,  	.remove = 	wm8993_remove,  	.suspend =	wm8993_suspend,  	.resume =	wm8993_resume, +	.set_bias_level = wm8993_set_bias_level, +	.reg_cache_size = sizeof(wm8993_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm8993_reg_defaults, +	.volatile_register = wm8993_volatile,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); -static int wm8993_i2c_probe(struct i2c_client *i2c, -			    const struct i2c_device_id *id) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, +				      const struct i2c_device_id *id)  {  	struct wm8993_priv *wm8993; -	struct snd_soc_codec *codec; -	unsigned int val;  	int ret; -	int i; - -	if (wm8993_codec) { -		dev_err(&i2c->dev, "A WM8993 is already registered\n"); -		return -EINVAL; -	}  	wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);  	if (wm8993 == NULL)  		return -ENOMEM; -	codec = &wm8993->codec; -	if (i2c->dev.platform_data) -		memcpy(&wm8993->pdata, i2c->dev.platform_data, -		       sizeof(wm8993->pdata)); - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->name = "WM8993"; -	codec->volatile_register = wm8993_volatile; -	codec->reg_cache = wm8993->reg_cache; -	codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8993_set_bias_level; -	codec->dai = &wm8993_dai; -	codec->num_dai = 1; -	snd_soc_codec_set_drvdata(codec, wm8993); - -	wm8993->hubs_data.hp_startup_mode = 1; -	wm8993->hubs_data.dcs_codes = -2; - -	memcpy(wm8993->reg_cache, wm8993_reg_defaults, -	       sizeof(wm8993->reg_cache)); - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} -  	i2c_set_clientdata(i2c, wm8993); -	codec->control_data = i2c; -	wm8993_codec = codec; - -	codec->dev = &i2c->dev; - -	for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) -		wm8993->supplies[i].supply = wm8993_supply_names[i]; - -	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), -				 wm8993->supplies); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to request supplies: %d\n", ret); -		goto err; -	} - -	ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), -				    wm8993->supplies); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); -		goto err_get; -	} - -	val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); -	if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { -		dev_err(codec->dev, "Invalid ID register value %x\n", val); -		ret = -EINVAL; -		goto err_enable; -	} - -	ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); -	if (ret != 0) -		goto err_enable; - -	codec->cache_only = 1; - -	/* By default we're using the output mixers */ -	wm8993->class_w_users = 2; - -	/* Latch volume update bits and default ZC on */ -	snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, -			    WM8993_DAC_VU, WM8993_DAC_VU); -	snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, -			    WM8993_ADC_VU, WM8993_ADC_VU); -	/* Manualy manage the HPOUT sequencing for independent stereo -	 * control. */ -	snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, -			    WM8993_HPOUT1_AUTO_PU, 0); - -	/* Use automatic clock configuration */ -	snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); - -	wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, -				      wm8993->pdata.lineout2_diff, -				      wm8993->pdata.lineout1fb, -				      wm8993->pdata.lineout2fb, -				      wm8993->pdata.jd_scthr, -				      wm8993->pdata.jd_thr, -				      wm8993->pdata.micbias1_lvl, -				      wm8993->pdata.micbias2_lvl); -			      -	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	if (ret != 0) -		goto err_enable; - -	wm8993_dai.dev = codec->dev; - -	ret = snd_soc_register_dai(&wm8993_dai); -	if (ret != 0) -		goto err_bias; - -	ret = snd_soc_register_codec(codec); - -	return 0; - -err_bias: -	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); -err_enable: -	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err_get: -	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err: -	wm8993_codec = NULL; -	kfree(wm8993); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm8993, &wm8993_dai, 1); +	if (ret < 0) +		kfree(wm8993);  	return ret;  } -static int wm8993_i2c_remove(struct i2c_client *client) +static __devexit int wm8993_i2c_remove(struct i2c_client *client)  { -	struct wm8993_priv *wm8993 = i2c_get_clientdata(client); - -	snd_soc_unregister_codec(&wm8993->codec); -	snd_soc_unregister_dai(&wm8993_dai); - -	wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); -	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -	kfree(wm8993); - +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1695,30 +1627,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);  static struct i2c_driver wm8993_i2c_driver = {  	.driver = { -		.name = "WM8993", +		.name = "wm8993-codec",  		.owner = THIS_MODULE,  	}, -	.probe = wm8993_i2c_probe, -	.remove = wm8993_i2c_remove, +	.probe =    wm8993_i2c_probe, +	.remove =   __devexit_p(wm8993_i2c_remove),  	.id_table = wm8993_i2c_id,  }; - +#endif  static int __init wm8993_modinit(void)  { -	int ret; - +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm8993_i2c_driver); -	if (ret != 0) -		pr_err("WM8993: Unable to register I2C driver: %d\n", ret); - +	if (ret != 0) { +		pr_err("WM8993: Unable to register I2C driver: %d\n", +		       ret); +	} +#endif  	return ret;  }  module_init(wm8993_modinit);  static void __exit wm8993_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm8993_i2c_driver); +#endif  }  module_exit(wm8993_exit); diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h index 30e71ca88dad..2184617b9611 100644 --- a/sound/soc/codecs/wm8993.h +++ b/sound/soc/codecs/wm8993.h @@ -1,9 +1,6 @@  #ifndef WM8993_H  #define WM8993_H -extern struct snd_soc_dai wm8993_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8993; -  #define WM8993_SYSCLK_MCLK     1  #define WM8993_SYSCLK_FLL      2 diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a87046a96f2a..7823f92413f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -36,9 +36,6 @@  #include "wm8994.h"  #include "wm_hubs.h" -static struct snd_soc_codec *wm8994_codec; -struct snd_soc_codec_device soc_codec_dev_wm8994; -  struct fll_config {  	int src;  	int in; @@ -71,7 +68,9 @@ struct wm8994_micdet {  /* codec private data */  struct wm8994_priv {  	struct wm_hubs_data hubs; -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data; +	struct snd_soc_codec *codec;  	u16 reg_cache[WM8994_REG_CACHE_SIZE + 1];  	int sysclk[2];  	int sysclk_rate[2]; @@ -1901,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,  	return snd_soc_put_volsw(kcontrol, ucontrol);  } - -  static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)  {  	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); @@ -1941,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,  			       struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);	 +	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	struct wm8994_pdata *pdata = wm8994->pdata;  	int drc = wm8994_get_drc(kcontrol->id.name);  	int value = ucontrol->value.integer.value[0]; @@ -2044,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,  					 struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);	 +	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	struct wm8994_pdata *pdata = wm8994->pdata;  	int block = wm8994_get_retune_mobile_block(kcontrol->id.name);  	int value = ucontrol->value.integer.value[0]; @@ -2066,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,  					 struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +	struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);  	int block = wm8994_get_retune_mobile_block(kcontrol->id.name);  	ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; @@ -2880,10 +2877,9 @@ static int wm8994_get_fll_config(struct fll_div *fll,  	return 0;  } -static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, +static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,  			  unsigned int freq_in, unsigned int freq_out)  { -	struct snd_soc_codec *codec = dai->codec;  	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	int reg_offset, ret;  	struct fll_div fll; @@ -2994,8 +2990,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,  	return 0;  } +  static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; +static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, +			  unsigned int freq_in, unsigned int freq_out) +{ +	return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); +} +  static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,  		int clk_id, unsigned int freq, int dir)  { @@ -3507,10 +3510,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {  	.set_tristate	= wm8994_set_tristate,  }; -struct snd_soc_dai wm8994_dai[] = { +static struct snd_soc_dai_driver wm8994_dai[] = {  	{ -		.name = "WM8994 AIF1", -		.id = 1, +		.name = "wm8994-aif1",  		.playback = {  			.stream_name = "AIF1 Playback",  			.channels_min = 2, @@ -3528,8 +3530,7 @@ struct snd_soc_dai wm8994_dai[] = {  		.ops = &wm8994_aif1_dai_ops,  	},  	{ -		.name = "WM8994 AIF2", -		.id = 2, +		.name = "wm8994-aif2",  		.playback = {  			.stream_name = "AIF2 Playback",  			.channels_min = 2, @@ -3547,8 +3548,7 @@ struct snd_soc_dai wm8994_dai[] = {  		.ops = &wm8994_aif2_dai_ops,  	},  	{ -		.name = "WM8994 AIF3", -		.id = 3, +		.name = "wm8994-aif3",  		.playback = {  			.stream_name = "AIF3 Playback",  			.channels_min = 2, @@ -3566,20 +3566,17 @@ struct snd_soc_dai wm8994_dai[] = {  		.ops = &wm8994_aif3_dai_ops,  	}  }; -EXPORT_SYMBOL_GPL(wm8994_dai);  #ifdef CONFIG_PM -static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	int i, ret;  	for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {  		memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],  		       sizeof(struct fll_config)); -		ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); +		ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0);  		if (ret < 0)  			dev_warn(codec->dev, "Failed to stop FLL%d: %d\n",  				 i + 1, ret); @@ -3590,10 +3587,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)  	return 0;  } -static int wm8994_resume(struct platform_device *pdev) +static int wm8994_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	u16 *reg_cache = codec->reg_cache;  	int i, ret; @@ -3622,7 +3617,7 @@ static int wm8994_resume(struct platform_device *pdev)  		if (!wm8994->fll_suspend[i].out)  			continue; -		ret = wm8994_set_fll(&codec->dai[0], i + 1, +		ret = _wm8994_set_fll(codec, i + 1,  				     wm8994->fll_suspend[i].src,  				     wm8994->fll_suspend[i].in,  				     wm8994->fll_suspend[i].out); @@ -3640,7 +3635,7 @@ static int wm8994_resume(struct platform_device *pdev)  static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)  { -	struct snd_soc_codec *codec = &wm8994->codec; +	struct snd_soc_codec *codec = wm8994->codec;  	struct wm8994_pdata *pdata = wm8994->pdata;  	struct snd_kcontrol_new controls[] = {  		SOC_ENUM_EXT("AIF1.1 EQ Mode", @@ -3698,16 +3693,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)  	wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;  	wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; -	ret = snd_soc_add_controls(&wm8994->codec, controls, +	ret = snd_soc_add_controls(wm8994->codec, controls,  				   ARRAY_SIZE(controls));  	if (ret != 0) -		dev_err(wm8994->codec.dev, +		dev_err(wm8994->codec->dev,  			"Failed to add ReTune Mobile controls: %d\n", ret);  }  static void wm8994_handle_pdata(struct wm8994_priv *wm8994)  { -	struct snd_soc_codec *codec = &wm8994->codec; +	struct snd_soc_codec *codec = wm8994->codec;  	struct wm8994_pdata *pdata = wm8994->pdata;  	int ret, i; @@ -3739,7 +3734,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)  		wm8994->drc_texts = kmalloc(sizeof(char *)  					    * pdata->num_drc_cfgs, GFP_KERNEL);  		if (!wm8994->drc_texts) { -			dev_err(wm8994->codec.dev, +			dev_err(wm8994->codec->dev,  				"Failed to allocate %d DRC config texts\n",  				pdata->num_drc_cfgs);  			return; @@ -3751,10 +3746,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)  		wm8994->drc_enum.max = pdata->num_drc_cfgs;  		wm8994->drc_enum.texts = wm8994->drc_texts; -		ret = snd_soc_add_controls(&wm8994->codec, controls, +		ret = snd_soc_add_controls(wm8994->codec, controls,  					   ARRAY_SIZE(controls));  		if (ret != 0) -			dev_err(wm8994->codec.dev, +			dev_err(wm8994->codec->dev,  				"Failed to add DRC mode controls: %d\n", ret);  		for (i = 0; i < WM8994_NUM_DRC; i++) @@ -3767,62 +3762,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)  	if (pdata->num_retune_mobile_cfgs)  		wm8994_handle_retune_mobile_pdata(wm8994);  	else -		snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, +		snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,  				     ARRAY_SIZE(wm8994_eq_controls));  } -static int wm8994_probe(struct platform_device *pdev) -{ -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; - -	if (wm8994_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; -	} - -	socdev->card->codec = wm8994_codec; -	codec = wm8994_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: %d\n", ret); -		return ret; -	} - -	wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec)); - -	wm_hubs_add_analogue_controls(codec); -	snd_soc_add_controls(codec, wm8994_snd_controls, -			     ARRAY_SIZE(wm8994_snd_controls)); -	snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, -				  ARRAY_SIZE(wm8994_dapm_widgets)); -	wm_hubs_add_analogue_routes(codec, 0, 0); -	snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); - -	return 0; -} - -static int wm8994_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_wm8994 = { -	.probe = 	wm8994_probe, -	.remove = 	wm8994_remove, -	.suspend = 	wm8994_suspend, -	.resume =	wm8994_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); -  /**   * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ   * @@ -3881,7 +3824,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect);  static irqreturn_t wm8994_mic_irq(int irq, void *data)  {  	struct wm8994_priv *priv = data; -	struct snd_soc_codec *codec = &priv->codec; +	struct snd_soc_codec *codec = priv->codec;  	int reg;  	int report; @@ -3913,47 +3856,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)  	return IRQ_HANDLED;  } -static int wm8994_codec_probe(struct platform_device *pdev) +static int wm8994_codec_probe(struct snd_soc_codec *codec)  { -	int ret;  	struct wm8994_priv *wm8994; -	struct snd_soc_codec *codec; -	int i; -	u16 rev; +	int ret, i, rev; -	if (wm8994_codec) { -		dev_err(&pdev->dev, "Another WM8994 is registered\n"); -		return -EINVAL; -	} +	codec->control_data = dev_get_drvdata(codec->dev->parent);  	wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); -	if (!wm8994) { -		dev_err(&pdev->dev, "Failed to allocate private data\n"); +	if (wm8994 == NULL)  		return -ENOMEM; -	} - -	codec = &wm8994->codec; - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -  	snd_soc_codec_set_drvdata(codec, wm8994); -	codec->control_data = dev_get_drvdata(pdev->dev.parent); -	codec->name = "WM8994"; -	codec->owner = THIS_MODULE; -	codec->read = wm8994_read; -	codec->write = wm8994_write; -	codec->readable_register = wm8994_readable; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm8994_set_bias_level; -	codec->dai = &wm8994_dai[0]; -	codec->num_dai = 3; -	codec->reg_cache_size = WM8994_MAX_REGISTER; -	codec->reg_cache = &wm8994->reg_cache; -	codec->dev = &pdev->dev; - -	wm8994->pdata = pdev->dev.parent->platform_data; + +	wm8994->pdata = dev_get_platdata(codec->dev->parent); +	wm8994->codec = codec;  	/* Fill the cache with physical values we inherited; don't reset */  	ret = wm8994_bulk_read(codec->control_data, 0, @@ -3989,25 +3905,25 @@ static int wm8994_codec_probe(struct platform_device *pdev)  	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,  				 wm8994_mic_irq, "Mic 1 detect", wm8994);  	if (ret != 0) -		dev_warn(&pdev->dev, +		dev_warn(codec->dev,  			 "Failed to request Mic1 detect IRQ: %d\n", ret);  	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,  				 wm8994_mic_irq, "Mic 1 short", wm8994);  	if (ret != 0) -		dev_warn(&pdev->dev, +		dev_warn(codec->dev,  			 "Failed to request Mic1 short IRQ: %d\n", ret);  	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,  				 wm8994_mic_irq, "Mic 2 detect", wm8994);  	if (ret != 0) -		dev_warn(&pdev->dev, +		dev_warn(codec->dev,  			 "Failed to request Mic2 detect IRQ: %d\n", ret);  	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,  				 wm8994_mic_irq, "Mic 2 short", wm8994);  	if (ret != 0) -		dev_warn(&pdev->dev, +		dev_warn(codec->dev,  			 "Failed to request Mic2 short IRQ: %d\n", ret);  	/* Remember if AIFnLRCLK is configured as a GPIO.  This should be @@ -4038,13 +3954,8 @@ static int wm8994_codec_probe(struct platform_device *pdev)  		wm8994->lrclk_shared[1] = 0;  	} -	for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) -		wm8994_dai[i].dev = codec->dev; -  	wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -	wm8994_codec = codec; -  	/* Latch volume updates (right only; we always do left then right). */  	snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,  			    WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); @@ -4081,24 +3992,18 @@ static int wm8994_codec_probe(struct platform_device *pdev)  	wm8994_update_class_w(codec); -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err_irq; -	} - -	ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); -		goto err_codec; -	} +	wm8994_handle_pdata(wm8994); -	platform_set_drvdata(pdev, wm8994); +	wm_hubs_add_analogue_controls(codec); +	snd_soc_add_controls(codec, wm8994_snd_controls, +			     ARRAY_SIZE(wm8994_snd_controls)); +	snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, +				  ARRAY_SIZE(wm8994_dapm_widgets)); +	wm_hubs_add_analogue_routes(codec, 0, 0); +	snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));  	return 0; -err_codec: -	snd_soc_unregister_codec(codec);  err_irq:  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); @@ -4109,31 +4014,50 @@ err:  	return ret;  } -static int __devexit wm8994_codec_remove(struct platform_device *pdev) +static int  wm8994_codec_remove(struct snd_soc_codec *codec)  { -	struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = &wm8994->codec; +	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); -	snd_soc_unregister_codec(&wm8994->codec); +  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);  	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);  	kfree(wm8994); -	wm8994_codec = NULL;  	return 0;  } +static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { +	.probe =	wm8994_codec_probe, +	.remove =	wm8994_codec_remove, +	.suspend =	wm8994_suspend, +	.resume =	wm8994_resume, +	.read = wm8994_read, +	.write = wm8994_write, +	.set_bias_level = wm8994_set_bias_level, +}; + +static int __devinit wm8994_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, +			wm8994_dai, ARRAY_SIZE(wm8994_dai)); +} + +static int __devexit wm8994_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} +  static struct platform_driver wm8994_codec_driver = {  	.driver = {  		   .name = "wm8994-codec",  		   .owner = THIS_MODULE,  		   }, -	.probe = wm8994_codec_probe, -	.remove = __devexit_p(wm8994_codec_remove), +	.probe = wm8994_probe, +	.remove = __devexit_p(wm8994_remove),  };  static __init int wm8994_init(void) diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 2e0ca67a8df7..d8dce260c430 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -11,9 +11,6 @@  #include <sound/soc.h> -extern struct snd_soc_codec_device soc_codec_dev_wm8994; -extern struct snd_soc_dai wm8994_dai[]; -  /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */  #define WM8994_SYSCLK_MCLK1 1  #define WM8994_SYSCLK_MCLK2 2 diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 76b37ff6c264..00249d5b6793 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -156,7 +156,8 @@ static struct {  };  struct wm9081_priv { -	struct snd_soc_codec codec; +	enum snd_soc_control_type control_type; +	void *control_data;  	u16 reg_cache[WM9081_MAX_REGISTER + 1];  	int sysclk_source;  	int mclk_rate; @@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = {  /* We report two channels because the CODEC processes a stereo signal, even   * though it is only capable of handling a mono output.   */ -struct snd_soc_dai wm9081_dai = { -	.name = "WM9081", +static struct snd_soc_dai_driver wm9081_dai = { +	.name = "wm9081-hifi",  	.playback = {  		.stream_name = "HiFi Playback",  		.channels_min = 1, @@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = {  	},  	.ops = &wm9081_dai_ops,  }; -EXPORT_SYMBOL_GPL(wm9081_dai); - -static struct snd_soc_codec *wm9081_codec; - -static int wm9081_probe(struct platform_device *pdev) +static int wm9081_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	struct wm9081_priv *wm9081; -	int ret = 0; +	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); +	int ret; +	u16 reg; -	if (wm9081_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	codec->control_data = wm9081->control_data; +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm9081_codec; -	codec = wm9081_codec; -	wm9081 = snd_soc_codec_get_drvdata(codec); +	reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); +	if (reg != 0x9081) { +		dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); +		ret = -EINVAL; +		return ret; +	} -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); +	ret = wm9081_reset(codec);  	if (ret < 0) { -		dev_err(codec->dev, "failed to create pcms: %d\n", ret); -		goto pcm_err; +		dev_err(codec->dev, "Failed to issue reset\n"); +		return ret;  	} +	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + +	/* Enable zero cross by default */ +	reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); +	snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); +	reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); +	snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, +		     reg | WM9081_SPKPGAZC); +  	snd_soc_add_controls(codec, wm9081_snd_controls,  			     ARRAY_SIZE(wm9081_snd_controls));  	if (!wm9081->retune) { @@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev)  	snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));  	return ret; - -pcm_err: -	return ret;  } -static int wm9081_remove(struct platform_device *pdev) +static int wm9081_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); - +	wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  }  #ifdef CONFIG_PM -static int wm9081_suspend(struct platform_device *pdev, pm_message_t state) +static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm9081_resume(struct platform_device *pdev) +static int wm9081_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	u16 *reg_cache = codec->reg_cache;  	int i; -	for (i = 0; i < codec->reg_cache_size; i++) { +	for (i = 0; i < codec->driver->reg_cache_size; i++) {  		if (i == WM9081_SOFTWARE_RESET)  			continue; @@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev)  #define wm9081_resume NULL  #endif -struct snd_soc_codec_device soc_codec_dev_wm9081 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {  	.probe = 	wm9081_probe,  	.remove = 	wm9081_remove,  	.suspend =	wm9081_suspend,  	.resume =	wm9081_resume, +	.set_bias_level = wm9081_set_bias_level, +	.reg_cache_size = sizeof(wm9081_reg_defaults), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm9081_reg_defaults, +	.volatile_register = wm9081_volatile_register,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081); - -static int wm9081_register(struct wm9081_priv *wm9081, -			   enum snd_soc_control_type control) -{ -	struct snd_soc_codec *codec = &wm9081->codec; -	int ret; -	u16 reg; - -	if (wm9081_codec) { -		dev_err(codec->dev, "Another WM9081 is registered\n"); -		ret = -EINVAL; -		goto err; -	} - -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	snd_soc_codec_set_drvdata(codec, wm9081); -	codec->name = "WM9081"; -	codec->owner = THIS_MODULE; -	codec->dai = &wm9081_dai; -	codec->num_dai = 1; -	codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache); -	codec->reg_cache = &wm9081->reg_cache; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm9081_set_bias_level; -	codec->volatile_register = wm9081_volatile_register; - -	memcpy(codec->reg_cache, wm9081_reg_defaults, -	       sizeof(wm9081_reg_defaults)); - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} - -	reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); -	if (reg != 0x9081) { -		dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); -		ret = -EINVAL; -		goto err; -	} - -	ret = wm9081_reset(codec); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to issue reset\n"); -		goto err; -	} - -	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -	/* Enable zero cross by default */ -	reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); -	snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); -	reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); -	snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, -		     reg | WM9081_SPKPGAZC); - -	wm9081_dai.dev = codec->dev; - -	wm9081_codec = codec; - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register codec: %d\n", ret); -		goto err; -	} - -	ret = snd_soc_register_dai(&wm9081_dai); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to register DAI: %d\n", ret); -		goto err_codec; -	} - -	return 0; - -err_codec: -	snd_soc_unregister_codec(codec); -err: -	kfree(wm9081); -	return ret; -} - -static void wm9081_unregister(struct wm9081_priv *wm9081) -{ -	wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF); -	snd_soc_unregister_dai(&wm9081_dai); -	snd_soc_unregister_codec(&wm9081->codec); -	kfree(wm9081); -	wm9081_codec = NULL; -} +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  {  	struct wm9081_priv *wm9081; -	struct snd_soc_codec *codec; +	int ret;  	wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);  	if (wm9081 == NULL)  		return -ENOMEM; -	codec = &wm9081->codec; -	codec->hw_write = (hw_write_t)i2c_master_send; -	wm9081->retune = i2c->dev.platform_data; -  	i2c_set_clientdata(i2c, wm9081); -	codec->control_data = i2c; - -	codec->dev = &i2c->dev; +	wm9081->control_data = i2c; -	return wm9081_register(wm9081, SND_SOC_I2C); +	ret = snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm9081, &wm9081_dai, 1); +	if (ret < 0) +		kfree(wm9081); +	return ret;  }  static __devexit int wm9081_i2c_remove(struct i2c_client *client)  { -	struct wm9081_priv *wm9081 = i2c_get_clientdata(client); -	wm9081_unregister(wm9081); +	snd_soc_unregister_codec(&client->dev); +	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);  static struct i2c_driver wm9081_i2c_driver = {  	.driver = { -		.name = "wm9081", +		.name = "wm9081-codec",  		.owner = THIS_MODULE,  	},  	.probe =    wm9081_i2c_probe,  	.remove =   __devexit_p(wm9081_i2c_remove),  	.id_table = wm9081_i2c_id,  }; +#endif  static int __init wm9081_modinit(void)  { -	int ret; - +	int ret = 0; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	ret = i2c_add_driver(&wm9081_i2c_driver);  	if (ret != 0) {  		printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",  		       ret);  	} - +#endif  	return ret;  }  module_init(wm9081_modinit);  static void __exit wm9081_exit(void)  { +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)  	i2c_del_driver(&wm9081_i2c_driver); +#endif  }  module_exit(wm9081_exit); diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h index 42d3bc757021..871cccb066dc 100644 --- a/sound/soc/codecs/wm9081.h +++ b/sound/soc/codecs/wm9081.h @@ -15,9 +15,6 @@  #include <sound/soc.h> -extern struct snd_soc_dai wm9081_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm9081; -  /*   * SYSCLK sources   */ diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 1592250daec0..7a1825418ee4 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -34,8 +34,6 @@  #include "wm9090.h" -static struct snd_soc_codec *wm9090_codec; -  static const u16 wm9090_reg_defaults[] = {  	0x9093,     /* R0   - Software Reset */  	0x0006,     /* R1   - Power Management (1) */ @@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = {  /* This struct is used to save the context */  struct wm9090_priv { -	/* We're not really registering as a CODEC since ASoC core -	 * does not yet support multiple CODECs but having the CODEC -	 * structure means we can reuse some of the ASoC core -	 * features. -	 */ -	struct snd_soc_codec codec;  	struct mutex mutex;  	u16 reg_cache[WM9090_MAX_REGISTER + 1];  	struct wm9090_platform_data pdata; +	void *control_data;  };  static int wm9090_volatile(unsigned int reg) @@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,  	case SND_SOC_BIAS_STANDBY:  		if (codec->bias_level == SND_SOC_BIAS_OFF) {  			/* Restore the register cache */ -			for (i = 1; i < codec->reg_cache_size; i++) { +			for (i = 1; i < codec->driver->reg_cache_size; i++) {  				if (reg_cache[i] == wm9090_reg_defaults[i])  					continue;  				if (wm9090_volatile(i)) @@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,  	return 0;  } -static int wm9090_probe(struct platform_device *pdev) +static int wm9090_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; -	int ret = 0; +	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); +	int ret; -	if (wm9090_codec == NULL) { -		dev_err(&pdev->dev, "Codec device not registered\n"); -		return -ENODEV; +	codec->control_data = wm9090->control_data; +	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); +	if (ret != 0) { +		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +		return ret;  	} -	socdev->card->codec = wm9090_codec; -	codec = wm9090_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: %d\n", ret); -		goto pcm_err; +	ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); +	if (ret < 0) +		return ret; +	if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { +		dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); +		return -EINVAL;  	} +	ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); +	if (ret < 0) +		return ret; + +	/* Configure some defaults; they will be written out when we +	 * bring the bias up. +	 */ +	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU +		| WM9090_IN1A_ZC; +	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU +		| WM9090_IN1B_ZC; +	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU +		| WM9090_IN2A_ZC; +	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU +		| WM9090_IN2B_ZC; +	wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= +		WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; +	wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= +		WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; +	wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= +		WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; + +	wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; + +	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +  	wm9090_add_controls(codec);  	return 0; - -pcm_err: -	return ret;  }  #ifdef CONFIG_PM -static int wm9090_suspend(struct platform_device *pdev, pm_message_t state) +static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm9090_resume(struct platform_device *pdev) +static int wm9090_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	return 0; @@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev)  #define wm9090_resume NULL  #endif -static int wm9090_remove(struct platform_device *pdev) +static int wm9090_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); - -	snd_soc_free_pcms(socdev); -	snd_soc_dapm_free(socdev); +	wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm9090 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {  	.probe = 	wm9090_probe,  	.remove = 	wm9090_remove,  	.suspend = 	wm9090_suspend,  	.resume =	wm9090_resume, +	.set_bias_level = wm9090_set_bias_level, +	.reg_cache_size = (WM9090_MAX_REGISTER + 1), +	.reg_word_size = sizeof(u16), +	.reg_cache_default = wm9090_reg_defaults, +	.volatile_register = wm9090_volatile,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090);  static int wm9090_i2c_probe(struct i2c_client *i2c,  			    const struct i2c_device_id *id)  {  	struct wm9090_priv *wm9090; -	struct snd_soc_codec *codec;  	int ret;  	wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); @@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,  		dev_err(&i2c->dev, "Can not allocate memory\n");  		return -ENOMEM;  	} -	codec = &wm9090->codec;  	if (i2c->dev.platform_data)  		memcpy(&wm9090->pdata, i2c->dev.platform_data,  		       sizeof(wm9090->pdata)); -	wm9090_codec = codec; -  	i2c_set_clientdata(i2c, wm9090); +	wm9090->control_data = i2c; +	mutex_init(&wm9090->mutex); -	mutex_init(&codec->mutex); -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); - -	codec->control_data = i2c; -	snd_soc_codec_set_drvdata(codec, wm9090); -	codec->dev = &i2c->dev; -	codec->name = "WM9090"; -	codec->owner = THIS_MODULE; -	codec->bias_level = SND_SOC_BIAS_OFF; -	codec->set_bias_level = wm9090_set_bias_level, -	codec->reg_cache_size = WM9090_MAX_REGISTER + 1; -	codec->reg_cache = &wm9090->reg_cache; -	codec->volatile_register = wm9090_volatile; - -	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); -	if (ret != 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		goto err; -	} - -	memcpy(&wm9090->reg_cache, wm9090_reg_defaults, -	       sizeof(wm9090->reg_cache)); - -	ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); -	if (ret < 0) -		goto err; -	if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { -		dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret); -		ret = -EINVAL; -		goto err; -	} - -	ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); +	ret =  snd_soc_register_codec(&i2c->dev, +			&soc_codec_dev_wm9090,  NULL, 0);  	if (ret < 0) -		goto err; - -	/* Configure some defaults; they will be written out when we -	 * bring the bias up. -	 */ -	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU -		| WM9090_IN1A_ZC; -	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU -		| WM9090_IN1B_ZC; -	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU -		| WM9090_IN2A_ZC; -	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU -		| WM9090_IN2B_ZC; -	wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= -		WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; -	wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=  -		WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; -	wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= -		WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; - -	wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; - -	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -	ret = snd_soc_register_codec(codec); -	if (ret != 0) { -		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); -		goto err_bias; -	} - -	return 0; - -err_bias: -	wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); -err: -	kfree(wm9090); -	i2c_set_clientdata(i2c, NULL); -	wm9090_codec = NULL; - +		kfree(wm9090);  	return ret;  }  static int wm9090_i2c_remove(struct i2c_client *i2c)  {  	struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); -	struct snd_soc_codec *codec = &wm9090->codec; -	snd_soc_unregister_codec(codec); -	wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); +	snd_soc_unregister_codec(&i2c->dev);  	kfree(wm9090); -	wm9090_codec = NULL;  	return 0;  } @@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);  static struct i2c_driver wm9090_i2c_driver = {  	.driver = { -		.name = "wm9090", +		.name = "wm9090-codec",  		.owner = THIS_MODULE,  	},  	.probe = wm9090_i2c_probe, diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h index b08eab932a5b..29b9d9fc70b4 100644 --- a/sound/soc/codecs/wm9090.h +++ b/sound/soc/codecs/wm9090.h @@ -23,8 +23,6 @@  #ifndef __WM9090_H  #define __WM9090_H -extern struct snd_soc_codec_device soc_codec_dev_wm9090; -  /*   * Register values.   */ diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 8793341849d1..e4d8f5339c51 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	int reg;  	u16 vra; @@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = {  	.prepare	= ac97_prepare,  }; -struct snd_soc_dai wm9705_dai[] = { +static struct snd_soc_dai_driver wm9705_dai[] = {  	{ -		.name = "AC97 HiFi", +		.name = "wm9705-hifi",  		.ac97_control = 1,  		.playback = {  			.stream_name = "HiFi Playback", @@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = {  		.ops = &wm9705_dai_ops,  	},  	{ -		.name = "AC97 Aux", +		.name = "wm9705-aux",  		.playback = {  			.stream_name = "Aux Playback",  			.channels_min = 1, @@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = {  		},  	}  }; -EXPORT_SYMBOL_GPL(wm9705_dai);  static int wm9705_reset(struct snd_soc_codec *codec)  { @@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec)  }  #ifdef CONFIG_PM -static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) +static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);  	return 0;  } -static int wm9705_soc_resume(struct platform_device *pdev) +static int wm9705_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i, ret;  	u16 *cache = codec->reg_cache; @@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev)  #define wm9705_soc_resume NULL  #endif -static int wm9705_soc_probe(struct platform_device *pdev) +static int wm9705_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec;  	int ret = 0;  	printk(KERN_INFO "WM9705 SoC Audio Codec\n"); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), -				      GFP_KERNEL); -	if (socdev->card->codec == NULL) -		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} -	codec->reg_cache_size = sizeof(wm9705_reg); -	codec->reg_cache_step = 2; - -	codec->name = "WM9705"; -	codec->owner = THIS_MODULE; -	codec->dai = wm9705_dai; -	codec->num_dai = ARRAY_SIZE(wm9705_dai); -	codec->write = ac97_write; -	codec->read = ac97_read; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) {  		printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); -		goto codec_err; +		return ret;  	} -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; -  	ret = wm9705_reset(codec);  	if (ret)  		goto reset_err; @@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev)  	return 0;  reset_err: -	snd_soc_free_pcms(socdev); -pcm_err:  	snd_soc_free_ac97_codec(codec); -codec_err: -	kfree(codec->reg_cache); -cache_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL;  	return ret;  } -static int wm9705_soc_remove(struct platform_device *pdev) +static int wm9705_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; - -	snd_soc_dapm_free(socdev); -	snd_soc_free_pcms(socdev);  	snd_soc_free_ac97_codec(codec); -	kfree(codec->reg_cache); -	kfree(codec);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm9705 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {  	.probe = 	wm9705_soc_probe,  	.remove = 	wm9705_soc_remove,  	.suspend =	wm9705_soc_suspend,  	.resume =	wm9705_soc_resume, +	.read = ac97_read, +	.write = ac97_write, +	.reg_cache_size = sizeof(wm9705_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_step = 2, +	.reg_cache_default = wm9705_reg, +}; + +static __devinit int wm9705_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); +} + +static int __devexit wm9705_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver wm9705_codec_driver = { +	.driver = { +			.name = "wm9705-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = wm9705_probe, +	.remove = __devexit_p(wm9705_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); + +static int __init wm9705_init(void) +{ +	return platform_driver_register(&wm9705_codec_driver); +} +module_init(wm9705_init); + +static void __exit wm9705_exit(void) +{ +	platform_driver_unregister(&wm9705_codec_driver); +} +module_exit(wm9705_exit);  MODULE_DESCRIPTION("ASoC WM9705 driver");  MODULE_AUTHOR("Ian Molton"); diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h index d380f110f9e2..23ea9ce47359 100644 --- a/sound/soc/codecs/wm9705.h +++ b/sound/soc/codecs/wm9705.h @@ -8,7 +8,4 @@  #define WM9705_DAI_AC97_HIFI	0  #define WM9705_DAI_AC97_AUX	1 -extern struct snd_soc_dai wm9705_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm9705; -  #endif diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 28790a2ffe8d..f8f37ae30910 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec =rtd->codec;  	int reg;  	u16 vra; @@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_codec *codec = socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	u16 vra, xsle;  	vra = ac97_read(codec, AC97_EXTENDED_STATUS); @@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = {  	.prepare	= ac97_aux_prepare,  }; -struct snd_soc_dai wm9712_dai[] = { +struct snd_soc_dai_driver wm9712_dai[] = {  { -	.name = "AC97 HiFi", +	.name = "wm9712-hifi",  	.ac97_control = 1,  	.playback = {  		.stream_name = "HiFi Playback", @@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = {  	.ops = &wm9712_dai_ops_hifi,  },  { -	.name = "AC97 Aux", +	.name = "wm9712-aux",  	.playback = {  		.stream_name = "Aux Playback",  		.channels_min = 1, @@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = {  	.ops = &wm9712_dai_ops_aux,  }  }; -EXPORT_SYMBOL_GPL(wm9712_dai);  static int wm9712_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level) @@ -597,20 +594,15 @@ err:  	return -EIO;  } -static int wm9712_soc_suspend(struct platform_device *pdev, +static int wm9712_soc_suspend(struct snd_soc_codec *codec,  	pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; -  	wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0;  } -static int wm9712_soc_resume(struct platform_device *pdev) +static int wm9712_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	int i, ret;  	u16 *cache = codec->reg_cache; @@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev)  	return ret;  } -static int wm9712_soc_probe(struct platform_device *pdev) +static int wm9712_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec;  	int ret = 0;  	printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), -				      GFP_KERNEL); -	if (socdev->card->codec == NULL) -		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); - -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} -	codec->reg_cache_size = sizeof(wm9712_reg); -	codec->reg_cache_step = 2; - -	codec->name = "WM9712"; -	codec->owner = THIS_MODULE; -	codec->dai = wm9712_dai; -	codec->num_dai = ARRAY_SIZE(wm9712_dai); -	codec->write = ac97_write; -	codec->read = ac97_read; -	codec->set_bias_level = wm9712_set_bias_level; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); -  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) {  		printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); -		goto codec_err; +		return ret;  	} -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; -  	ret = wm9712_reset(codec, 0);  	if (ret < 0) {  		printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); @@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev)  	return 0;  reset_err: -	snd_soc_free_pcms(socdev); -pcm_err:  	snd_soc_free_ac97_codec(codec); - -codec_err: -	kfree(codec->reg_cache); - -cache_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL;  	return ret;  } -static int wm9712_soc_remove(struct platform_device *pdev) +static int wm9712_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; - -	snd_soc_dapm_free(socdev); -	snd_soc_free_pcms(socdev);  	snd_soc_free_ac97_codec(codec); -	kfree(codec->reg_cache); -	kfree(codec);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm9712 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {  	.probe = 	wm9712_soc_probe,  	.remove = 	wm9712_soc_remove,  	.suspend =	wm9712_soc_suspend,  	.resume =	wm9712_soc_resume, +	.read = ac97_read, +	.write = ac97_write, +	.set_bias_level = wm9712_set_bias_level, +	.reg_cache_size = sizeof(wm9712_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_step = 2, +	.reg_cache_default = wm9712_reg,  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); + +static __devinit int wm9712_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); +} + +static int __devexit wm9712_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver wm9712_codec_driver = { +	.driver = { +			.name = "wm9712-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = wm9712_probe, +	.remove = __devexit_p(wm9712_remove), +}; + +static int __init wm9712_init(void) +{ +	return platform_driver_register(&wm9712_codec_driver); +} +module_init(wm9712_init); + +static void __exit wm9712_exit(void) +{ +	platform_driver_unregister(&wm9712_codec_driver); +} +module_exit(wm9712_exit);  MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");  MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h index d29e8a18ca6d..fb69c3aa4ed0 100644 --- a/sound/soc/codecs/wm9712.h +++ b/sound/soc/codecs/wm9712.h @@ -8,7 +8,4 @@  #define WM9712_DAI_AC97_HIFI	0  #define WM9712_DAI_AC97_AUX		1 -extern struct snd_soc_dai wm9712_dai[2]; -extern struct snd_soc_codec_device soc_codec_dev_wm9712; -  #endif diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 34e0c91092fa..463917e762b5 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = {  	.set_tristate	= wm9713_set_dai_tristate,  }; -struct snd_soc_dai wm9713_dai[] = { +static struct snd_soc_dai_driver wm9713_dai[] = {  { -	.name = "AC97 HiFi", +	.name = "wm9713-hifi",  	.ac97_control = 1,  	.playback = {  		.stream_name = "HiFi Playback", @@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = {  	.ops = &wm9713_dai_ops_hifi,  	},  	{ -	.name = "AC97 Aux", +	.name = "wm9713-aux",  	.playback = {  		.stream_name = "Aux Playback",  		.channels_min = 1, @@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = {  	.ops = &wm9713_dai_ops_aux,  	},  	{ -	.name = "WM9713 Voice", +	.name = "wm9713-voice",  	.playback = {  		.stream_name = "Voice Playback",  		.channels_min = 1, @@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = {  	.symmetric_rates = 1,  	},  }; -EXPORT_SYMBOL_GPL(wm9713_dai);  int wm9713_reset(struct snd_soc_codec *codec, int try_warm)  { @@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,  	return 0;  } -static int wm9713_soc_suspend(struct platform_device *pdev, +static int wm9713_soc_suspend(struct snd_soc_codec *codec,  	pm_message_t state)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	u16 reg;  	/* Disable everything except touchpanel - that will be handled @@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev,  	return 0;  } -static int wm9713_soc_resume(struct platform_device *pdev) +static int wm9713_soc_resume(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec;  	struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);  	int i, ret;  	u16 *cache = codec->reg_cache; @@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev)  	return ret;  } -static int wm9713_soc_probe(struct platform_device *pdev) +static int wm9713_soc_probe(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec; +	struct wm9713_priv *wm9713;  	int ret = 0, reg; -	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), -				      GFP_KERNEL); -	if (socdev->card->codec == NULL) +	wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); +	if (wm9713 == NULL)  		return -ENOMEM; -	codec = socdev->card->codec; -	mutex_init(&codec->mutex); - -	codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); -	if (codec->reg_cache == NULL) { -		ret = -ENOMEM; -		goto cache_err; -	} -	codec->reg_cache_size = sizeof(wm9713_reg); -	codec->reg_cache_step = 2; - -	snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv), -						 GFP_KERNEL)); -	if (snd_soc_codec_get_drvdata(codec) == NULL) { -		ret = -ENOMEM; -		goto priv_err; -	} - -	codec->name = "WM9713"; -	codec->owner = THIS_MODULE; -	codec->dai = wm9713_dai; -	codec->num_dai = ARRAY_SIZE(wm9713_dai); -	codec->write = ac97_write; -	codec->read = ac97_read; -	codec->set_bias_level = wm9713_set_bias_level; -	INIT_LIST_HEAD(&codec->dapm_widgets); -	INIT_LIST_HEAD(&codec->dapm_paths); +	snd_soc_codec_set_drvdata(codec, wm9713);  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0)  		goto codec_err; -	/* register pcms */ -	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); -	if (ret < 0) -		goto pcm_err; -  	/* do a cold reset for the controller and then try  	 * a warm reset followed by an optional cold reset for codec */  	wm9713_reset(codec, 0); @@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev)  	return 0;  reset_err: -	snd_soc_free_pcms(socdev); -pcm_err:  	snd_soc_free_ac97_codec(codec); -  codec_err: -	kfree(snd_soc_codec_get_drvdata(codec)); - -priv_err: -	kfree(codec->reg_cache); - -cache_err: -	kfree(socdev->card->codec); -	socdev->card->codec = NULL; +	kfree(wm9713);  	return ret;  } -static int wm9713_soc_remove(struct platform_device *pdev) +static int wm9713_soc_remove(struct snd_soc_codec *codec)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_codec *codec = socdev->card->codec; - -	if (codec == NULL) -		return 0; - -	snd_soc_dapm_free(socdev); -	snd_soc_free_pcms(socdev); +	struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);  	snd_soc_free_ac97_codec(codec); -	kfree(snd_soc_codec_get_drvdata(codec)); -	kfree(codec->reg_cache); -	kfree(codec); +	kfree(wm9713);  	return 0;  } -struct snd_soc_codec_device soc_codec_dev_wm9713 = { +static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {  	.probe = 	wm9713_soc_probe,  	.remove = 	wm9713_soc_remove,  	.suspend =	wm9713_soc_suspend,  	.resume = 	wm9713_soc_resume, +	.read = ac97_read, +	.write = ac97_write, +	.set_bias_level = wm9713_set_bias_level, +	.reg_cache_size = sizeof(wm9713_reg), +	.reg_word_size = sizeof(u16), +	.reg_cache_step = 2, +	.reg_cache_default = wm9713_reg, +}; + +static __devinit int wm9713_probe(struct platform_device *pdev) +{ +	return snd_soc_register_codec(&pdev->dev, +			&soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); +} + +static int __devexit wm9713_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_codec(&pdev->dev); +	return 0; +} + +static struct platform_driver wm9713_codec_driver = { +	.driver = { +			.name = "wm9713-codec", +			.owner = THIS_MODULE, +	}, + +	.probe = wm9713_probe, +	.remove = __devexit_p(wm9713_remove),  }; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713); + +static int __init wm9713_init(void) +{ +	return platform_driver_register(&wm9713_codec_driver); +} +module_init(wm9713_init); + +static void __exit wm9713_exit(void) +{ +	platform_driver_unregister(&wm9713_codec_driver); +} +module_exit(wm9713_exit);  MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");  MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 63b8d81756e3..793da863a03d 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h @@ -45,9 +45,6 @@  #define WM9713_DAI_AC97_AUX		1  #define WM9713_DAI_PCM_VOICE	2 -extern struct snd_soc_codec_device soc_codec_dev_wm9713; -extern struct snd_soc_dai wm9713_dai[3]; -  int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);  #endif diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 97f74d6a33e6..2b07b17a6b2d 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -28,12 +28,9 @@  #include <mach/mux.h>  #include "../codecs/tlv320aic3x.h" -#include "../codecs/cq93vc.h" -#include "../codecs/spdif_transciever.h"  #include "davinci-pcm.h"  #include "davinci-i2s.h"  #include "davinci-mcasp.h" -#include "davinci-vcif.h"  #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \  		SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) @@ -41,8 +38,8 @@ static int evm_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret = 0;  	unsigned sysclk; @@ -87,7 +84,7 @@ static int evm_spdif_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 *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	/* set cpu DAI configuration */  	return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); @@ -132,8 +129,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  };  /* Logic for a aic3x as connected on a davinci-evm */ -static int evm_aic3x_init(struct snd_soc_codec *codec) +static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	/* Add davinci-evm specific widgets */  	snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,  				  ARRAY_SIZE(aic3x_dapm_widgets)); @@ -161,8 +160,10 @@ static int evm_aic3x_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link evm_dai = {  	.name = "TLV320AIC3X",  	.stream_name = "AIC3X", -	.cpu_dai = &davinci_i2s_dai, -	.codec_dai = &aic3x_dai, +	.cpu_dai_name = "davinci-mcasp.0", +	.codec_dai_name = "tlv320aic3x-hifi", +	.codec_name = "tlv320aic3x-codec.0-001a", +	.platform_name = "davinci-pcm-audio",  	.init = evm_aic3x_init,  	.ops = &evm_ops,  }; @@ -171,40 +172,49 @@ static struct snd_soc_dai_link dm365_evm_dai = {  #ifdef CONFIG_SND_DM365_AIC3X_CODEC  	.name = "TLV320AIC3X",  	.stream_name = "AIC3X", -	.cpu_dai = &davinci_i2s_dai, -	.codec_dai = &aic3x_dai, +	.cpu_dai_name = "davinci-i2s", +	.codec_dai_name = "tlv320aic3x-hifi",  	.init = evm_aic3x_init, +	.codec_name = "tlv320aic3x-codec.0-001a",  	.ops = &evm_ops,  #elif defined(CONFIG_SND_DM365_VOICE_CODEC)  	.name = "Voice Codec - CQ93VC",  	.stream_name = "CQ93", -	.cpu_dai = &davinci_vcif_dai, -	.codec_dai = &cq93vc_dai, +	.cpu_dai_name = "davinci-vcif", +	.codec_dai_name = "cq93vc-hifi", +	.codec_name = "cq93vc-codec",  #endif +	.platform_name = "davinci-pcm-audio",  };  static struct snd_soc_dai_link dm6467_evm_dai[] = {  	{  		.name = "TLV320AIC3X",  		.stream_name = "AIC3X", -		.cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], -		.codec_dai = &aic3x_dai, +		.cpu_dai_name= "davinci-mcasp.0", +		.codec_dai_name = "tlv320aic3x-hifi", +		.platform_name ="davinci-pcm-audio", +		.codec_name = "tlv320aic3x-codec.0-001a",  		.init = evm_aic3x_init,  		.ops = &evm_ops,  	},  	{  		.name = "McASP",  		.stream_name = "spdif", -		.cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], -		.codec_dai = &dit_stub_dai, +		.cpu_dai_name= "davinci-mcasp.1", +		.codec_dai_name = "dit-hifi", +		.codec_name = "spdif_dit", +		.platform_name = "davinci-pcm-audio",  		.ops = &evm_spdif_ops,  	},  };  static struct snd_soc_dai_link da8xx_evm_dai = {  	.name = "TLV320AIC3X",  	.stream_name = "AIC3X", -	.cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], -	.codec_dai = &aic3x_dai, +	.cpu_dai_name= "davinci-mcasp.0", +	.codec_dai_name = "tlv320aic3x-hifi", +	.codec_name = "tlv320aic3x-codec.0-001a", +	.platform_name = "davinci-pcm-audio",  	.init = evm_aic3x_init,  	.ops = &evm_ops,  }; @@ -212,7 +222,6 @@ static struct snd_soc_dai_link da8xx_evm_dai = {  /* davinci dm6446, dm355 evm audio machine driver */  static struct snd_soc_card snd_soc_card_evm = {  	.name = "DaVinci EVM", -	.platform = &davinci_soc_platform,  	.dai_link = &evm_dai,  	.num_links = 1,  }; @@ -220,16 +229,13 @@ static struct snd_soc_card snd_soc_card_evm = {  /* davinci dm365 evm audio machine driver */  static struct snd_soc_card dm365_snd_soc_card_evm = {  	.name = "DaVinci DM365 EVM", -	.platform = &davinci_soc_platform,  	.dai_link = &dm365_evm_dai,  	.num_links = 1,  }; -  /* davinci dm6467 evm audio machine driver */  static struct snd_soc_card dm6467_snd_soc_card_evm = {  	.name = "DaVinci DM6467 EVM", -	.platform = &davinci_soc_platform,  	.dai_link = dm6467_evm_dai,  	.num_links = ARRAY_SIZE(dm6467_evm_dai),  }; @@ -237,82 +243,40 @@ static struct snd_soc_card dm6467_snd_soc_card_evm = {  static struct snd_soc_card da830_snd_soc_card = {  	.name = "DA830/OMAP-L137 EVM",  	.dai_link = &da8xx_evm_dai, -	.platform = &davinci_soc_platform,  	.num_links = 1,  };  static struct snd_soc_card da850_snd_soc_card = {  	.name = "DA850/OMAP-L138 EVM",  	.dai_link = &da8xx_evm_dai, -	.platform = &davinci_soc_platform,  	.num_links = 1,  }; -static struct aic3x_setup_data aic3x_setup; - -/* evm audio subsystem */ -static struct snd_soc_device evm_snd_devdata = { -	.card = &snd_soc_card_evm, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &aic3x_setup, -}; - -/* evm audio subsystem */ -static struct snd_soc_device dm365_evm_snd_devdata = { -	.card = &dm365_snd_soc_card_evm, -#ifdef CONFIG_SND_DM365_AIC3X_CODEC -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &aic3x_setup, -#elif defined(CONFIG_SND_DM365_VOICE_CODEC) -	.codec_dev = &soc_codec_dev_cq93vc, -#endif -}; - -/* evm audio subsystem */ -static struct snd_soc_device dm6467_evm_snd_devdata = { -	.card = &dm6467_snd_soc_card_evm, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &aic3x_setup, -}; - -/* evm audio subsystem */ -static struct snd_soc_device da830_evm_snd_devdata = { -	.card = &da830_snd_soc_card, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &aic3x_setup, -}; - -static struct snd_soc_device da850_evm_snd_devdata = { -	.card		= &da850_snd_soc_card, -	.codec_dev	= &soc_codec_dev_aic3x, -	.codec_data	= &aic3x_setup, -}; -  static struct platform_device *evm_snd_device;  static int __init evm_init(void)  { -	struct snd_soc_device *evm_snd_dev_data; +	struct snd_soc_card *evm_snd_dev_data;  	int index;  	int ret;  	if (machine_is_davinci_evm()) { -		evm_snd_dev_data = &evm_snd_devdata; +		evm_snd_dev_data = &snd_soc_card_evm;  		index = 0;  	} else if (machine_is_davinci_dm355_evm()) { -		evm_snd_dev_data = &evm_snd_devdata; +		evm_snd_dev_data = &snd_soc_card_evm;  		index = 1;  	} else if (machine_is_davinci_dm365_evm()) { -		evm_snd_dev_data = &dm365_evm_snd_devdata; +		evm_snd_dev_data = &dm365_snd_soc_card_evm;  		index = 0;  	} else if (machine_is_davinci_dm6467_evm()) { -		evm_snd_dev_data = &dm6467_evm_snd_devdata; +		evm_snd_dev_data = &dm6467_snd_soc_card_evm;  		index = 0;  	} else if (machine_is_davinci_da830_evm()) { -		evm_snd_dev_data = &da830_evm_snd_devdata; +		evm_snd_dev_data = &da830_snd_soc_card;  		index = 1;  	} else if (machine_is_davinci_da850_evm()) { -		evm_snd_dev_data = &da850_evm_snd_devdata; +		evm_snd_dev_data = &da850_snd_soc_card;  		index = 0;  	} else  		return -EINVAL; @@ -322,7 +286,6 @@ static int __init evm_init(void)  		return -ENOMEM;  	platform_set_drvdata(evm_snd_device, evm_snd_dev_data); -	evm_snd_dev_data->dev = &evm_snd_device->dev;  	ret = platform_device_add(evm_snd_device);  	if (ret)  		platform_device_put(evm_snd_device); diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 9e8932abf158..9f8b6c556866 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,  		struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_platform *platform = socdev->card->platform; +	struct snd_soc_platform *platform = rtd->platform;  	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);  	u32 spcr;  	u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; @@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,  	if (playback) {  		/* Stop the DMA to avoid data loss */  		/* while the transmitter is out of reset to handle XSYNCERR */ -		if (platform->pcm_ops->trigger) { -			int ret = platform->pcm_ops->trigger(substream, +		if (platform->driver->ops->trigger) { +			int ret = platform->driver->ops->trigger(substream,  				SNDRV_PCM_TRIGGER_STOP);  			if (ret < 0)  				printk(KERN_DEBUG "Playback DMA stop failed\n"); @@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,  		toggle_clock(dev, playback);  		/* Restart the DMA */ -		if (platform->pcm_ops->trigger) { -			int ret = platform->pcm_ops->trigger(substream, +		if (platform->driver->ops->trigger) { +			int ret = platform->driver->ops->trigger(substream,  				SNDRV_PCM_TRIGGER_START);  			if (ret < 0)  				printk(KERN_DEBUG "Playback DMA start failed\n"); @@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)  static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,  				   unsigned int fmt)  { -	struct davinci_mcbsp_dev *dev = cpu_dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	unsigned int pcr;  	unsigned int srgr;  	/* Attention srgr is updated by hw_params! */ @@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,  static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,  				int div_id, int div)  { -	struct davinci_mcbsp_dev *dev = cpu_dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	if (div_id != DAVINCI_MCBSP_CLKGDV)  		return -ENODEV; @@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *dai)  { -	struct davinci_mcbsp_dev *dev = dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);  	struct davinci_pcm_dma_params *dma_params =  					&dev->dma_params[substream->stream];  	struct snd_interval *i = NULL; @@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,  	snd_pcm_format_t fmt;  	unsigned element_cnt = 1; +	dai->capture_dma_data = dev->dma_params; +	dai->playback_dma_data = dev->dma_params; +  	/* general line settings */  	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);  	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -569,7 +571,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,  static int davinci_i2s_prepare(struct snd_pcm_substream *substream,  		struct snd_soc_dai *dai)  { -	struct davinci_mcbsp_dev *dev = dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);  	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);  	davinci_mcbsp_stop(dev, playback);  	if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { @@ -582,7 +584,7 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream,  static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  			       struct snd_soc_dai *dai)  { -	struct davinci_mcbsp_dev *dev = dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);  	int ret = 0;  	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);  	if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) @@ -608,7 +610,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,  		struct snd_soc_dai *dai)  { -	struct davinci_mcbsp_dev *dev = dai->private_data; +	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);  	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);  	davinci_mcbsp_stop(dev, playback);  } @@ -625,9 +627,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {  }; -struct snd_soc_dai davinci_i2s_dai = { -	.name = "davinci-i2s", -	.id = 0, +static struct snd_soc_dai_driver davinci_i2s_dai = {  	.playback = {  		.channels_min = 2,  		.channels_max = 2, @@ -641,7 +641,6 @@ struct snd_soc_dai davinci_i2s_dai = {  	.ops = &davinci_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(davinci_i2s_dai);  static int davinci_i2s_probe(struct platform_device *pdev)  { @@ -720,10 +719,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)  	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;  	dev->dev = &pdev->dev; -	davinci_i2s_dai.private_data = dev; -	davinci_i2s_dai.capture.dma_data = dev->dma_params; -	davinci_i2s_dai.playback.dma_data = dev->dma_params; -	ret = snd_soc_register_dai(&davinci_i2s_dai); +	dev_set_drvdata(&pdev->dev, dev); + +	ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);  	if (ret != 0)  		goto err_free_mem; @@ -739,10 +737,10 @@ err_release_region:  static int davinci_i2s_remove(struct platform_device *pdev)  { -	struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; +	struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);  	struct resource *mem; -	snd_soc_unregister_dai(&davinci_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev);  	clk_disable(dev->clk);  	clk_put(dev->clk);  	dev->clk = NULL; @@ -757,7 +755,7 @@ static struct platform_driver davinci_mcbsp_driver = {  	.probe		= davinci_i2s_probe,  	.remove		= davinci_i2s_remove,  	.driver		= { -		.name	= "davinci-asp", +		.name	= "davinci-i2s",  		.owner	= THIS_MODULE,  	},  }; diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h index 0b1e77b8c279..48dac3e2521a 100644 --- a/sound/soc/davinci/davinci-i2s.h +++ b/sound/soc/davinci/davinci-i2s.h @@ -17,6 +17,4 @@ enum davinci_mcbsp_div {  	DAVINCI_MCBSP_CLKGDV,              /* Sample rate generator divider */  }; -extern struct snd_soc_dai davinci_i2s_dai; -  #endif diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b24720894af6..c8e97dcbfff4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -422,7 +422,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)  static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,  					 unsigned int fmt)  { -	struct davinci_audio_dev *dev = cpu_dai->private_data; +	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	void __iomem *base = dev->base;  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -709,12 +709,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,  					struct snd_pcm_hw_params *params,  					struct snd_soc_dai *cpu_dai)  { -	struct davinci_audio_dev *dev = cpu_dai->private_data; +	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	struct davinci_pcm_dma_params *dma_params =  					&dev->dma_params[substream->stream];  	int word_length;  	u8 fifo_level; +	cpu_dai->capture_dma_data = dev->dma_params; +	cpu_dai->playback_dma_data = dev->dma_params; +  	davinci_hw_common_param(dev, substream->stream);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)  		fifo_level = dev->txnumevt; @@ -761,8 +764,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,  static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,  				     int cmd, struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data; +	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	int ret = 0;  	switch (cmd) { @@ -804,10 +806,9 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {  }; -struct snd_soc_dai davinci_mcasp_dai[] = { +static struct snd_soc_dai_driver davinci_mcasp_dai[] = {  	{ -		.name 		= "davinci-i2s", -		.id 		= 0, +		.name		= "davinci-mcasp.0",  		.playback	= {  			.channels_min	= 2,  			.channels_max 	= 2, @@ -828,8 +829,7 @@ struct snd_soc_dai davinci_mcasp_dai[] = {  	},  	{ -		.name 		= "davinci-dit", -		.id 		= 1, +		"davinci-mcasp.1",  		.playback 	= {  			.channels_min	= 1,  			.channels_max	= 384, @@ -840,7 +840,6 @@ struct snd_soc_dai davinci_mcasp_dai[] = {  	},  }; -EXPORT_SYMBOL_GPL(davinci_mcasp_dai);  static int davinci_mcasp_probe(struct platform_device *pdev)  { @@ -917,11 +916,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)  	}  	dma_data->channel = res->start; -	davinci_mcasp_dai[pdata->op_mode].private_data = dev; -	davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params; -	davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params; -	davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; -	ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); +	dev_set_drvdata(&pdev->dev, dev); +	ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);  	if (ret != 0)  		goto err_release_region; @@ -937,12 +933,10 @@ err_release_data:  static int davinci_mcasp_remove(struct platform_device *pdev)  { -	struct snd_platform_data *pdata = pdev->dev.platform_data; -	struct davinci_audio_dev *dev; +	struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);  	struct resource *mem; -	snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); -	dev = davinci_mcasp_dai[pdata->op_mode].private_data; +	snd_soc_unregister_dai(&pdev->dev);  	clk_disable(dev->clk);  	clk_put(dev->clk);  	dev->clk = NULL; diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index e755b5121ec7..4681acc63606 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -22,8 +22,6 @@  #include <mach/asp.h>  #include "davinci-pcm.h" -extern struct snd_soc_dai davinci_mcasp_dai[]; -  #define DAVINCI_MCASP_RATES	SNDRV_PCM_RATE_8000_96000  #define DAVINCI_MCASP_I2S_DAI	0  #define DAVINCI_MCASP_DIT_DAI	1 diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index a7124116d2e0..9d35b8c1a624 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -653,7 +653,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)  	struct davinci_pcm_dma_params *pa;  	struct davinci_pcm_dma_params *params; -	pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	if (!pa)  		return -ENODEV;  	params = &pa[substream->stream]; @@ -821,7 +821,7 @@ static int davinci_pcm_new(struct snd_card *card,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = 0xffffffff; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = davinci_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK,  			pcm_hardware_playback.buffer_bytes_max); @@ -829,7 +829,7 @@ static int davinci_pcm_new(struct snd_card *card,  			return ret;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = davinci_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE,  			pcm_hardware_capture.buffer_bytes_max); @@ -840,25 +840,44 @@ static int davinci_pcm_new(struct snd_card *card,  	return 0;  } -struct snd_soc_platform davinci_soc_platform = { -	.name = 	"davinci-audio", -	.pcm_ops = 	&davinci_pcm_ops, +static struct snd_soc_platform_driver davinci_soc_platform = { +	.ops =		&davinci_pcm_ops,  	.pcm_new = 	davinci_pcm_new,  	.pcm_free = 	davinci_pcm_free,  }; -EXPORT_SYMBOL_GPL(davinci_soc_platform); -static int __init davinci_soc_platform_init(void) +static int __devinit davinci_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&davinci_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform);  } -module_init(davinci_soc_platform_init); -static void __exit davinci_soc_platform_exit(void) +static int __devexit davinci_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&davinci_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver davinci_pcm_driver = { +	.driver = { +			.name = "davinci-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = davinci_soc_platform_probe, +	.remove = __devexit_p(davinci_soc_platform_remove), +}; + +static int __init snd_davinci_pcm_init(void) +{ +	return platform_driver_register(&davinci_pcm_driver); +} +module_init(snd_davinci_pcm_init); + +static void __exit snd_davinci_pcm_exit(void) +{ +	platform_driver_unregister(&davinci_pcm_driver);  } -module_exit(davinci_soc_platform_exit); +module_exit(snd_davinci_pcm_exit);  MODULE_AUTHOR("Vladimir Barinov");  MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index b799a02333d8..c0d6c9be4b4d 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -28,7 +28,4 @@ struct davinci_pcm_dma_params {  	unsigned int fifo_level;  }; - -extern struct snd_soc_platform davinci_soc_platform; -  #endif diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 40eccfe9e358..997c54f3693c 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -29,7 +29,6 @@  #include <asm/plat-sffsdr/sffsdr-fpga.h>  #endif -#include <mach/mcbsp.h>  #include <mach/edma.h>  #include "../codecs/pcm3008.h" @@ -48,7 +47,7 @@ static int sffsdr_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 *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int fs;  	int ret = 0; @@ -85,15 +84,16 @@ static struct snd_soc_ops sffsdr_ops = {  static struct snd_soc_dai_link sffsdr_dai = {  	.name = "PCM3008", /* Codec name */  	.stream_name = "PCM3008 HiFi", -	.cpu_dai = &davinci_i2s_dai, -	.codec_dai = &pcm3008_dai, +	.cpu_dai_name = "davinci-asp.0", +	.codec_dai_name = "pcm3008-hifi", +	.codec_name = "pcm3008-codec", +	.platform_name = "davinci-pcm-audio",  	.ops = &sffsdr_ops,  };  /* davinci-sffsdr audio machine driver */  static struct snd_soc_card snd_soc_sffsdr = {  	.name = "DaVinci SFFSDR", -	.platform = &davinci_soc_platform,  	.dai_link = &sffsdr_dai,  	.num_links = 1,  }; @@ -106,11 +106,12 @@ static struct pcm3008_setup_data sffsdr_pcm3008_setup = {  	.pdda_pin = GPIO(38),  }; -/* sffsdr audio subsystem */ -static struct snd_soc_device sffsdr_snd_devdata = { -	.card = &snd_soc_sffsdr, -	.codec_dev = &soc_codec_dev_pcm3008, -	.codec_data = &sffsdr_pcm3008_setup, +struct platform_device pcm3008_codec = { +		.name = "pcm3008-codec", +		.id = 0, +		.dev = { +				.platform_data = &sffsdr_pcm3008_setup, +		},  };  static struct resource sffsdr_snd_resources[] = { @@ -135,14 +136,15 @@ static int __init sffsdr_init(void)  	if (!machine_is_sffsdr())  		return -EINVAL; +	platform_device_register(&pcm3008_codec); +  	sffsdr_snd_device = platform_device_alloc("soc-audio", 0);  	if (!sffsdr_snd_device) {  		printk(KERN_ERR "platform device allocation failed\n");  		return -ENOMEM;  	} -	platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); -	sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; +	platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr);  	platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data,  				 sizeof(sffsdr_snd_data)); @@ -168,6 +170,7 @@ error:  static void __exit sffsdr_exit(void)  {  	platform_device_unregister(sffsdr_snd_device); +	platform_device_unregister(&pcm3008_codec);  }  module_init(sffsdr_init); diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index 48678533da7a..ea232f6a2c21 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -36,7 +36,6 @@  #include "davinci-pcm.h"  #include "davinci-i2s.h" -#include "davinci-vcif.h"  #define MOD_REG_BIT(val, mask, set) do { \  	if (set) { \ @@ -55,7 +54,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct davinci_vcif_dev *davinci_vcif_dev = -					rtd->dai->cpu_dai->private_data; +			snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;  	u32 w; @@ -74,7 +73,7 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct davinci_vcif_dev *davinci_vcif_dev = -					rtd->dai->cpu_dai->private_data; +			snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;  	u32 w; @@ -92,12 +91,15 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,  				  struct snd_pcm_hw_params *params,  				  struct snd_soc_dai *dai)  { -	struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data; +	struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai);  	struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;  	struct davinci_pcm_dma_params *dma_params =  			&davinci_vcif_dev->dma_params[substream->stream];  	u32 w; +	dai->capture_dma_data = davinci_vcif_dev->dma_params; +	dai->playback_dma_data = davinci_vcif_dev->dma_params; +  	/* Restart the codec before setup */  	davinci_vcif_stop(substream);  	davinci_vcif_start(substream); @@ -179,8 +181,7 @@ static struct snd_soc_dai_ops davinci_vcif_dai_ops = {  	.hw_params	= davinci_vcif_hw_params,  }; -struct snd_soc_dai davinci_vcif_dai = { -	.name = "davinci-vcif", +static struct snd_soc_dai_driver davinci_vcif_dai = {  	.playback = {  		.channels_min = 1,  		.channels_max = 2, @@ -194,7 +195,6 @@ struct snd_soc_dai davinci_vcif_dai = {  	.ops = &davinci_vcif_dai_ops,  }; -EXPORT_SYMBOL_GPL(davinci_vcif_dai);  static int davinci_vcif_probe(struct platform_device *pdev)  { @@ -222,12 +222,9 @@ static int davinci_vcif_probe(struct platform_device *pdev)  	davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =  					davinci_vc->davinci_vcif.dma_rx_addr; -	davinci_vcif_dai.dev = &pdev->dev; -	davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params; -	davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params; -	davinci_vcif_dai.private_data = davinci_vcif_dev; +	dev_set_drvdata(&pdev->dev, davinci_vcif_dev); -	ret = snd_soc_register_dai(&davinci_vcif_dai); +	ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai);  	if (ret != 0) {  		dev_err(&pdev->dev, "could not register dai\n");  		goto fail; @@ -243,7 +240,7 @@ fail:  static int davinci_vcif_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&davinci_vcif_dai); +	snd_soc_unregister_dai(&pdev->dev);  	return 0;  } @@ -252,7 +249,7 @@ static struct platform_driver davinci_vcif_driver = {  	.probe		= davinci_vcif_probe,  	.remove		= davinci_vcif_remove,  	.driver		= { -		.name	= "davinci_vcif", +		.name	= "davinci-vcif",  		.owner	= THIS_MODULE,  	},  }; diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h deleted file mode 100644 index 571c9948724f..000000000000 --- a/sound/soc/davinci/davinci-vcif.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * ALSA SoC Voice Codec Interface for TI DAVINCI processor - * - * Copyright (C) 2010 Texas Instruments. - * - * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _DAVINCI_VCIF_H -#define _DAVINCI_VCIF_H - -extern struct snd_soc_dai davinci_vcif_dai; - -#endif diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index 00b946632184..4f4873359613 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c @@ -31,7 +31,6 @@  #include <mach/dma.h>  #include "ep93xx-pcm.h" -#include "ep93xx-i2s.h"  #define EP93XX_I2S_TXCLKCFG		0x00  #define EP93XX_I2S_RXCLKCFG		0x04 @@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,  			      struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	snd_soc_dai_set_dma_data(cpu_dai, substream,  				 &info->dma_params[substream->stream]); @@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,  static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,  				struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);  	ep93xx_i2s_disable(info, substream->stream);  } @@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,  static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,  				  unsigned int fmt)  { -	struct ep93xx_i2s_info *info = cpu_dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);  	unsigned int clk_cfg, lin_ctrl;  	clk_cfg  = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); @@ -242,9 +240,7 @@ static int ep93xx_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; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct ep93xx_i2s_info *info = cpu_dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);  	unsigned word_len, div, sdiv, lrdiv;  	int found = 0, err; @@ -302,7 +298,7 @@ out:  static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,  				 unsigned int freq, int dir)  { -	struct ep93xx_i2s_info *info = cpu_dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);  	if (dir == SND_SOC_CLOCK_IN || clk_id != 0)  		return -EINVAL; @@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,  #ifdef CONFIG_PM  static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)  { -	struct ep93xx_i2s_info *info = dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);  	if (!dai->active)  		return; @@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)  static int ep93xx_i2s_resume(struct snd_soc_dai *dai)  { -	struct ep93xx_i2s_info *info = dai->private_data; +	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);  	if (!dai->active)  		return; @@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {  			    SNDRV_PCM_FMTBIT_S24_LE | \  			    SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai ep93xx_i2s_dai = { -	.name		= "ep93xx-i2s", -	.id		= 0, +static struct snd_soc_dai_driver ep93xx_i2s_dai = {  	.symmetric_rates= 1,  	.suspend	= ep93xx_i2s_suspend,  	.resume		= ep93xx_i2s_resume, @@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = {  	},  	.ops		= &ep93xx_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);  static int ep93xx_i2s_probe(struct platform_device *pdev)  { @@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)  		goto fail;  	} -	ep93xx_i2s_dai.dev = &pdev->dev; -	ep93xx_i2s_dai.private_data = info; +	dev_set_drvdata(&pdev->dev, info);  	info->dma_params = ep93xx_i2s_dma_params;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)  		goto fail_put_sclk;  	} -	err = snd_soc_register_dai(&ep93xx_i2s_dai); +	err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);  	if (err)  		goto fail_put_lrclk; @@ -447,9 +439,9 @@ fail:  static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)  { -	struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; +	struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); -	snd_soc_unregister_dai(&ep93xx_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev);  	clk_put(info->lrclk);  	clk_put(info->sclk);  	clk_put(info->mclk); diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h deleted file mode 100644 index 3bd4ebfaa1de..000000000000 --- a/sound/soc/ep93xx/ep93xx-i2s.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * linux/sound/soc/ep93xx-i2s.h - * EP93xx I2S driver - * - * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> - *   - * 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 _EP93XX_SND_SOC_I2S_H -#define _EP93XX_SND_SOC_I2S_H - -extern struct snd_soc_dai ep93xx_i2s_dai; - -#endif /* _EP93XX_SND_SOC_I2S_H */ diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 4ba938400791..2f121ddbe4bb 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie,  static int ep93xx_pcm_open(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;  	struct ep93xx_pcm_dma_params *dma_params;  	struct ep93xx_runtime_data *rtd;      	int ret; @@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = 0xffffffff; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = ep93xx_pcm_preallocate_dma_buffer(pcm,  					SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			return ret;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = ep93xx_pcm_preallocate_dma_buffer(pcm,  					SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	return 0;  } -struct snd_soc_platform ep93xx_soc_platform = { -	.name		= "ep93xx-audio", -	.pcm_ops	= &ep93xx_pcm_ops, +static struct snd_soc_platform_driver ep93xx_soc_platform = { +	.ops		= &ep93xx_pcm_ops,  	.pcm_new	= &ep93xx_pcm_new,  	.pcm_free	= &ep93xx_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(ep93xx_soc_platform); + +static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) +{ +	return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); +} + +static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver ep93xx_pcm_driver = { +	.driver = { +			.name = "ep93xx-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = ep93xx_soc_platform_probe, +	.remove = __devexit_p(ep93xx_soc_platform_remove), +};  static int __init ep93xx_soc_platform_init(void)  { -	return snd_soc_register_platform(&ep93xx_soc_platform); +	return platform_driver_register(&ep93xx_pcm_driver);  }  static void __exit ep93xx_soc_platform_exit(void)  { -	snd_soc_unregister_platform(&ep93xx_soc_platform); +	platform_driver_unregister(&ep93xx_pcm_driver);  }  module_init(ep93xx_soc_platform_init); diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h index 4ffdd3f62fe9..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/ep93xx/ep93xx-pcm.h @@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params {  	int	dma_port;  }; -extern struct snd_soc_platform ep93xx_soc_platform; -  #endif /* _EP93XX_SND_SOC_PCM_H */ diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c index 64955340ff75..28ab5ff772ac 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/ep93xx/snappercl15.c @@ -22,7 +22,6 @@  #include "../codecs/tlv320aic23.h"  #include "ep93xx-pcm.h" -#include "ep93xx-i2s.h"  #define CODEC_CLOCK 5644800 @@ -30,8 +29,8 @@ static int snappercl15_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int err;  	err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | @@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MICIN", NULL, "Mic Jack"},  }; -static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) +static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,  				  ARRAY_SIZE(tlv320aic23_dapm_widgets)); @@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link snappercl15_dai = {  	.name		= "tlv320aic23",  	.stream_name	= "AIC23", -	.cpu_dai	= &ep93xx_i2s_dai, -	.codec_dai	= &tlv320aic23_dai, +	.cpu_dai_name	= "ep93xx-i2s", +	.codec_dai_name	= "tlv320aic23-hifi", +	.codec_name	= "tlv320aic23-codec.0-001a", +	.platform_name	=  "ep93xx-pcm-audio",  	.init		= snappercl15_tlv320aic23_init,  	.ops		= &snappercl15_ops,  };  static struct snd_soc_card snd_soc_snappercl15 = {  	.name		= "Snapper CL15", -	.platform	= &ep93xx_soc_platform,  	.dai_link	= &snappercl15_dai,  	.num_links	= 1,  }; -static struct snd_soc_device snappercl15_snd_devdata = { -	.card		= &snd_soc_snappercl15, -	.codec_dev	= &soc_codec_dev_tlv320aic23, -}; -  static struct platform_device *snappercl15_snd_device;  static int __init snappercl15_init(void) @@ -126,8 +123,7 @@ static int __init snappercl15_init(void)  	if (!snappercl15_snd_device)  		return -ENOMEM; -	platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); -	snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev; +	platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);  	ret = platform_device_add(snappercl15_snd_device);  	if (ret)  		platform_device_put(snappercl15_snd_device); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8cb65ccad35f..981868700388 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,6 +1,3 @@ -config SND_SOC_OF_SIMPLE -	tristate -	  config SND_MPC52xx_DMA  	tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index a83a73967ec6..7e472a53fcd3 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -1,6 +1,3 @@ -# Simple machine driver that extracts configuration from the OF device tree -obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o -  # MPC8610 HPCD Machine Support  snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o  obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 1a5b8e0d6a34..53251e6b5bd5 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -24,7 +24,6 @@  #include <sound/pcm_params.h>  #include <sound/initval.h>  #include <sound/soc.h> -#include <sound/soc-of-simple.h>  #include "mpc5200_dma.h"  #include "mpc5200_psc_ac97.h" @@ -32,21 +31,24 @@  #define DRV_NAME "efika-audio-fabric" -static struct snd_soc_device device;  static struct snd_soc_card card;  static struct snd_soc_dai_link efika_fabric_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 Analog", -	.codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG], -	.cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], +	.codec_dai_name = "stac9766-hifi-analog", +	.cpu_dai_name = "mpc5200-psc-ac97.0", +	.platform_name = "mpc5200-pcm-audio", +	.codec_name = "stac9766-codec",  },  {  	.name = "AC97",  	.stream_name = "AC97 IEC958", -	.codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL], -	.cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], +	.codec_dai_name = "stac9766-hifi-IEC958", +	.cpu_dai_name = "mpc5200-psc-ac97.1", +	.platform_name = "mpc5200-pcm-audio", +	.codec_name = "stac9766-codec",  },  }; @@ -58,13 +60,10 @@ static __init int efika_fabric_init(void)  	if (!of_machine_is_compatible("bplan,efika"))  		return -ENODEV; -	card.platform = &mpc5200_audio_dma_platform;  	card.name = "Efika";  	card.dai_link = efika_fabric_dai;  	card.num_links = ARRAY_SIZE(efika_fabric_dai); -	device.card = &card; -	device.codec_dev = &soc_codec_dev_stac9766;  	pdev = platform_device_alloc("soc-audio", 1);  	if (!pdev) { @@ -72,8 +71,7 @@ static __init int efika_fabric_init(void)  		return -ENODEV;  	} -	platform_set_drvdata(pdev, &device); -	device.dev = &pdev->dev; +	platform_set_drvdata(pdev, &card);  	rc = platform_device_add(pdev);  	if (rc) { diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 410c7496a18d..57774cb91ae3 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -3,10 +3,11 @@   *   * Author: Timur Tabi <timur@freescale.com>   * - * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed - * under the terms of the GNU General Public License version 2.  This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2.  This program is licensed "as is" without any warranty of any + * kind, whether express or implied.   *   * This driver implements ASoC support for the Elo DMA controller, which is   * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, @@ -20,6 +21,8 @@  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/gfp.h> +#include <linux/of_platform.h> +#include <linux/list.h>  #include <sound/core.h>  #include <sound/pcm.h> @@ -29,6 +32,7 @@  #include <asm/io.h>  #include "fsl_dma.h" +#include "fsl_ssi.h"	/* For the offset of stx0 and srx0 */  /*   * The formats that the DMA controller supports, which is anything @@ -52,26 +56,15 @@  #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \  			  SNDRV_PCM_RATE_CONTINUOUS) -/* DMA global data.  This structure is used by fsl_dma_open() to determine - * which DMA channels to assign to a substream.  Unfortunately, ASoC V1 does - * not allow the machine driver to provide this information to the PCM - * driver in advance, and there's no way to differentiate between the two - * DMA controllers.  So for now, this driver only supports one SSI device - * using two DMA channels.  We cannot support multiple DMA devices. - * - * ssi_stx_phys: bus address of SSI STX register - * ssi_srx_phys: bus address of SSI SRX register - * dma_channel: pointer to the DMA channel's registers - * irq: IRQ for this DMA channel - * assigned: set to 1 if that DMA channel is assigned to a substream - */ -static struct { +struct dma_object { +	struct snd_soc_platform_driver dai;  	dma_addr_t ssi_stx_phys;  	dma_addr_t ssi_srx_phys; -	struct ccsr_dma_channel __iomem *dma_channel[2]; -	unsigned int irq[2]; -	unsigned int assigned[2]; -} dma_global_data; +	struct ccsr_dma_channel __iomem *channel; +	unsigned int irq; +	bool assigned; +	char path[1]; +};  /*   * The number of DMA links to use.  Two is the bare minimum, but if you @@ -88,8 +81,6 @@ static struct {   * structure.   *   * @link[]: array of link descriptors - * @controller_id: which DMA controller (0, 1, ...) - * @channel_id: which DMA channel on the controller (0, 1, 2, ...)   * @dma_channel: pointer to the DMA channel's registers   * @irq: IRQ for this DMA channel   * @substream: pointer to the substream object, needed by the ISR @@ -104,8 +95,6 @@ static struct {   */  struct fsl_dma_private {  	struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; -	unsigned int controller_id; -	unsigned int channel_id;  	struct ccsr_dma_channel __iomem *dma_channel;  	unsigned int irq;  	struct snd_pcm_substream *substream; @@ -185,13 +174,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)  	struct fsl_dma_link_descriptor *link =  		&dma_private->link[dma_private->current_link]; -	/* Update our link descriptors to point to the next period */ -	if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -		link->source_addr = -			cpu_to_be32(dma_private->dma_buf_next); -	else -		link->dest_addr = -			cpu_to_be32(dma_private->dma_buf_next); +	/* Update our link descriptors to point to the next period. On a 36-bit +	 * system, we also need to update the ESAD bits.  We also set (keep) the +	 * snoop bits.  See the comments in fsl_dma_hw_params() about snooping. +	 */ +	if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +		link->source_addr = cpu_to_be32(dma_private->dma_buf_next); +#ifdef CONFIG_PHYS_64BIT +		link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | +			upper_32_bits(dma_private->dma_buf_next)); +#endif +	} else { +		link->dest_addr = cpu_to_be32(dma_private->dma_buf_next); +#ifdef CONFIG_PHYS_64BIT +		link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | +			upper_32_bits(dma_private->dma_buf_next)); +#endif +	}  	/* Update our variables for next time */  	dma_private->dma_buf_next += dma_private->period_size; @@ -212,6 +211,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)  static irqreturn_t fsl_dma_isr(int irq, void *dev_id)  {  	struct fsl_dma_private *dma_private = dev_id; +	struct snd_pcm_substream *substream = dma_private->substream; +	struct snd_soc_pcm_runtime *rtd = substream->private_data; +	struct device *dev = rtd->platform->dev;  	struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;  	irqreturn_t ret = IRQ_NONE;  	u32 sr, sr2 = 0; @@ -222,11 +224,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)  	sr = in_be32(&dma_channel->sr);  	if (sr & CCSR_DMA_SR_TE) { -		dev_err(dma_private->substream->pcm->card->dev, -			"DMA transmit error (controller=%u channel=%u irq=%u\n", -			dma_private->controller_id, -			dma_private->channel_id, irq); -		fsl_dma_abort_stream(dma_private->substream); +		dev_err(dev, "dma transmit error\n"); +		fsl_dma_abort_stream(substream);  		sr2 |= CCSR_DMA_SR_TE;  		ret = IRQ_HANDLED;  	} @@ -235,11 +234,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)  		ret = IRQ_HANDLED;  	if (sr & CCSR_DMA_SR_PE) { -		dev_err(dma_private->substream->pcm->card->dev, -			"DMA%u programming error (channel=%u irq=%u)\n", -			dma_private->controller_id, -			dma_private->channel_id, irq); -		fsl_dma_abort_stream(dma_private->substream); +		dev_err(dev, "dma programming error\n"); +		fsl_dma_abort_stream(substream);  		sr2 |= CCSR_DMA_SR_PE;  		ret = IRQ_HANDLED;  	} @@ -253,8 +249,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)  		ret = IRQ_HANDLED;  	if (sr & CCSR_DMA_SR_EOSI) { -		struct snd_pcm_substream *substream = dma_private->substream; -  		/* Tell ALSA we completed a period. */  		snd_pcm_period_elapsed(substream); @@ -288,11 +282,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)   * This function is called when the codec driver calls snd_soc_new_pcms(),   * once for each .dai_link in the machine driver's snd_soc_card   * structure. + * + * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which + * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM + * is specified. Therefore, any DMA buffers we allocate will always be in low + * memory, but we support for 36-bit physical addresses anyway. + * + * Regardless of where the memory is actually allocated, since the device can + * technically DMA to any 36-bit address, we do need to set the DMA mask to 36.   */  static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  	struct snd_pcm *pcm)  { -	static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); +	static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);  	int ret;  	if (!card->dev->dma_mask) @@ -305,10 +307,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  		fsl_dma_hardware.buffer_bytes_max,  		&pcm->streams[0].substream->dma_buffer);  	if (ret) { -		dev_err(card->dev, -			"Can't allocate playback DMA buffer (size=%u)\n", -			fsl_dma_hardware.buffer_bytes_max); -		return -ENOMEM; +		dev_err(card->dev, "can't allocate playback dma buffer\n"); +		return ret;  	}  	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, @@ -316,10 +316,8 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  		&pcm->streams[1].substream->dma_buffer);  	if (ret) {  		snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); -		dev_err(card->dev, -			"Can't allocate capture DMA buffer (size=%u)\n", -			fsl_dma_hardware.buffer_bytes_max); -		return -ENOMEM; +		dev_err(card->dev, "can't allocate capture dma buffer\n"); +		return ret;  	}  	return 0; @@ -390,6 +388,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  static int fsl_dma_open(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime; +	struct snd_soc_pcm_runtime *rtd = substream->private_data; +	struct device *dev = rtd->platform->dev; +	struct dma_object *dma = +		container_of(rtd->platform->driver, struct dma_object, dai);  	struct fsl_dma_private *dma_private;  	struct ccsr_dma_channel __iomem *dma_channel;  	dma_addr_t ld_buf_phys; @@ -407,52 +409,44 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)  	ret = snd_pcm_hw_constraint_integer(runtime,  		SNDRV_PCM_HW_PARAM_PERIODS);  	if (ret < 0) { -		dev_err(substream->pcm->card->dev, "invalid buffer size\n"); +		dev_err(dev, "invalid buffer size\n");  		return ret;  	}  	channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; -	if (dma_global_data.assigned[channel]) { -		dev_err(substream->pcm->card->dev, -			"DMA channel already assigned\n"); +	if (dma->assigned) { +		dev_err(dev, "dma channel already assigned\n");  		return -EBUSY;  	} -	dma_private = dma_alloc_coherent(substream->pcm->card->dev, -		sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); +	dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private), +					 &ld_buf_phys, GFP_KERNEL);  	if (!dma_private) { -		dev_err(substream->pcm->card->dev, -			"can't allocate DMA private data\n"); +		dev_err(dev, "can't allocate dma private data\n");  		return -ENOMEM;  	}  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -		dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys; +		dma_private->ssi_sxx_phys = dma->ssi_stx_phys;  	else -		dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys; +		dma_private->ssi_sxx_phys = dma->ssi_srx_phys; -	dma_private->dma_channel = dma_global_data.dma_channel[channel]; -	dma_private->irq = dma_global_data.irq[channel]; +	dma_private->dma_channel = dma->channel; +	dma_private->irq = dma->irq;  	dma_private->substream = substream;  	dma_private->ld_buf_phys = ld_buf_phys;  	dma_private->dma_buf_phys = substream->dma_buffer.addr; -	/* We only support one DMA controller for now */ -	dma_private->controller_id = 0; -	dma_private->channel_id = channel; -  	ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private);  	if (ret) { -		dev_err(substream->pcm->card->dev, -			"can't register ISR for IRQ %u (ret=%i)\n", +		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",  			dma_private->irq, ret); -		dma_free_coherent(substream->pcm->card->dev, -			sizeof(struct fsl_dma_private), +		dma_free_coherent(dev, sizeof(struct fsl_dma_private),  			dma_private, dma_private->ld_buf_phys);  		return ret;  	} -	dma_global_data.assigned[channel] = 1; +	dma->assigned = 1;  	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);  	snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); @@ -546,6 +540,8 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct fsl_dma_private *dma_private = runtime->private_data; +	struct snd_soc_pcm_runtime *rtd = substream->private_data; +	struct device *dev = rtd->platform->dev;  	/* Number of bits per sample */  	unsigned int sample_size = @@ -606,8 +602,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,  		break;  	default:  		/* We should never get here */ -		dev_err(substream->pcm->card->dev, -			"unsupported sample size %u\n", sample_size); +		dev_err(dev, "unsupported sample size %u\n", sample_size);  		return -EINVAL;  	} @@ -631,12 +626,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,  		link->count = cpu_to_be32(period_size); -		/* Even though the DMA controller supports 36-bit addressing, -		 * for simplicity we allow only 32-bit addresses for the audio -		 * buffer itself.  This was enforced in fsl_dma_new() with the -		 * DMA mask. -		 * -		 * The snoop bit tells the DMA controller whether it should tell +		/* The snoop bit tells the DMA controller whether it should tell  		 * the ECM to snoop during a read or write to an address. For  		 * audio, we use DMA to transfer data between memory and an I/O  		 * device (the SSI's STX0 or SRX0 register). Snooping is only @@ -651,20 +641,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,  		 * flush out the data for the previous period.  So if you  		 * increased period_bytes_min to a large enough size, you might  		 * get more performance by not snooping, and you'll still be -		 * okay. +		 * okay.  You'll need to update fsl_dma_update_pointers() also.  		 */  		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {  			link->source_addr = cpu_to_be32(temp_addr); -			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); +			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | +				upper_32_bits(temp_addr));  			link->dest_addr = cpu_to_be32(ssi_sxx_phys); -			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); +			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | +				upper_32_bits(ssi_sxx_phys));  		} else {  			link->source_addr = cpu_to_be32(ssi_sxx_phys); -			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); +			link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | +				upper_32_bits(ssi_sxx_phys));  			link->dest_addr = cpu_to_be32(temp_addr); -			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); +			link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | +				upper_32_bits(temp_addr));  		}  		temp_addr += period_size; @@ -689,14 +683,29 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct fsl_dma_private *dma_private = runtime->private_data; +	struct snd_soc_pcm_runtime *rtd = substream->private_data; +	struct device *dev = rtd->platform->dev;  	struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;  	dma_addr_t position;  	snd_pcm_uframes_t frames; -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +	/* Obtain the current DMA pointer, but don't read the ESAD bits if we +	 * only have 32-bit DMA addresses.  This function is typically called +	 * in interrupt context, so we need to optimize it. +	 */ +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {  		position = in_be32(&dma_channel->sar); -	else +#ifdef CONFIG_PHYS_64BIT +		position |= (u64)(in_be32(&dma_channel->satr) & +				  CCSR_DMA_ATR_ESAD_MASK) << 32; +#endif +	} else {  		position = in_be32(&dma_channel->dar); +#ifdef CONFIG_PHYS_64BIT +		position |= (u64)(in_be32(&dma_channel->datr) & +				  CCSR_DMA_ATR_ESAD_MASK) << 32; +#endif +	}  	/*  	 * When capture is started, the SSI immediately starts to fill its FIFO. @@ -710,8 +719,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)  	if ((position < dma_private->dma_buf_phys) ||  	    (position > dma_private->dma_buf_end)) { -		dev_err(substream->pcm->card->dev, -			"dma pointer is out of range, halting stream\n"); +		dev_err(dev, "dma pointer is out of range, halting stream\n");  		return SNDRV_PCM_POS_XRUN;  	} @@ -772,26 +780,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct fsl_dma_private *dma_private = runtime->private_data; -	int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; +	struct snd_soc_pcm_runtime *rtd = substream->private_data; +	struct device *dev = rtd->platform->dev; +	struct dma_object *dma = +		container_of(rtd->platform->driver, struct dma_object, dai);  	if (dma_private) {  		if (dma_private->irq)  			free_irq(dma_private->irq, dma_private);  		if (dma_private->ld_buf_phys) { -			dma_unmap_single(substream->pcm->card->dev, -				dma_private->ld_buf_phys, -				sizeof(dma_private->link), DMA_TO_DEVICE); +			dma_unmap_single(dev, dma_private->ld_buf_phys, +					 sizeof(dma_private->link), +					 DMA_TO_DEVICE);  		}  		/* Deallocate the fsl_dma_private structure */ -		dma_free_coherent(substream->pcm->card->dev, -			sizeof(struct fsl_dma_private), -			dma_private, dma_private->ld_buf_phys); +		dma_free_coherent(dev, sizeof(struct fsl_dma_private), +				  dma_private, dma_private->ld_buf_phys);  		substream->runtime->private_data = NULL;  	} -	dma_global_data.assigned[dir] = 0; +	dma->assigned = 0;  	return 0;  } @@ -814,6 +824,37 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)  	}  } +/** + * find_ssi_node -- returns the SSI node that points to his DMA channel node + * + * Although this DMA driver attempts to operate independently of the other + * devices, it still needs to determine some information about the SSI device + * that it's working with.  Unfortunately, the device tree does not contain + * a pointer from the DMA channel node to the SSI node -- the pointer goes the + * other way.  So we need to scan the device tree for SSI nodes until we find + * the one that points to the given DMA channel node.  It's ugly, but at least + * it's contained in this one function. + */ +static struct device_node *find_ssi_node(struct device_node *dma_channel_np) +{ +	struct device_node *ssi_np, *np; + +	for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") { +		/* Check each DMA phandle to see if it points to us.  We +		 * assume that device_node pointers are a valid comparison. +		 */ +		np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); +		if (np == dma_channel_np) +			return ssi_np; + +		np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); +		if (np == dma_channel_np) +			return ssi_np; +	} + +	return NULL; +} +  static struct snd_pcm_ops fsl_dma_ops = {  	.open   	= fsl_dma_open,  	.close  	= fsl_dma_close, @@ -823,59 +864,102 @@ static struct snd_pcm_ops fsl_dma_ops = {  	.pointer	= fsl_dma_pointer,  }; -struct snd_soc_platform fsl_soc_platform = { -	.name   	= "fsl-dma", -	.pcm_ops	= &fsl_dma_ops, -	.pcm_new	= fsl_dma_new, -	.pcm_free       = fsl_dma_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(fsl_soc_platform); +static int __devinit fsl_soc_dma_probe(struct of_device *of_dev, +				       const struct of_device_id *match) + { +	struct dma_object *dma; +	struct device_node *np = of_dev->dev.of_node; +	struct device_node *ssi_np; +	struct resource res; +	int ret; -/** - * fsl_dma_configure: store the DMA parameters from the fabric driver. - * - * This function is called by the ASoC fabric driver to give us the DMA and - * SSI channel information. - * - * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI - * data when a substream is created, so for now we need to store this data - * into a global variable.  This means that we can only support one DMA - * controller, and hence only one SSI. - */ -int fsl_dma_configure(struct fsl_dma_info *dma_info) +	/* Find the SSI node that points to us. */ +	ssi_np = find_ssi_node(np); +	if (!ssi_np) { +		dev_err(&of_dev->dev, "cannot find parent SSI node\n"); +		return -ENODEV; +	} + +	ret = of_address_to_resource(ssi_np, 0, &res); +	of_node_put(ssi_np); +	if (ret) { +		dev_err(&of_dev->dev, "could not determine device resources\n"); +		return ret; +	} + +	dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); +	if (!dma) { +		dev_err(&of_dev->dev, "could not allocate dma object\n"); +		return -ENOMEM; +	} + +	strcpy(dma->path, np->full_name); +	dma->dai.ops = &fsl_dma_ops; +	dma->dai.pcm_new = fsl_dma_new; +	dma->dai.pcm_free = fsl_dma_free_dma_buffers; + +	/* Store the SSI-specific information that we need */ +	dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); +	dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); + +	ret = snd_soc_register_platform(&of_dev->dev, &dma->dai); +	if (ret) { +		dev_err(&of_dev->dev, "could not register platform\n"); +		kfree(dma); +		return ret; +	} + +	dma->channel = of_iomap(np, 0); +	dma->irq = irq_of_parse_and_map(np, 0); + +	dev_set_drvdata(&of_dev->dev, dma); + +	return 0; +} + +static int __devexit fsl_soc_dma_remove(struct of_device *of_dev)  { -	static int initialized; +	struct dma_object *dma = dev_get_drvdata(&of_dev->dev); -	/* We only support one DMA controller for now */ -	if (initialized) -		return 0; +	snd_soc_unregister_platform(&of_dev->dev); +	iounmap(dma->channel); +	irq_dispose_mapping(dma->irq); +	kfree(dma); -	dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys; -	dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys; -	dma_global_data.dma_channel[0] = dma_info->dma_channel[0]; -	dma_global_data.dma_channel[1] = dma_info->dma_channel[1]; -	dma_global_data.irq[0] = dma_info->dma_irq[0]; -	dma_global_data.irq[1] = dma_info->dma_irq[1]; -	dma_global_data.assigned[0] = 0; -	dma_global_data.assigned[1] = 0; - -	initialized = 1; -	return 1; +	return 0;  } -EXPORT_SYMBOL_GPL(fsl_dma_configure); -static int __init fsl_soc_platform_init(void) +static const struct of_device_id fsl_soc_dma_ids[] = { +	{ .compatible = "fsl,ssi-dma-channel", }, +	{} +}; +MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids); + +static struct of_platform_driver fsl_soc_dma_driver = { +	.driver = { +		.name = "fsl-pcm-audio", +		.owner = THIS_MODULE, +		.of_match_table = fsl_soc_dma_ids, +	}, +	.probe = fsl_soc_dma_probe, +	.remove = __devexit_p(fsl_soc_dma_remove), +}; + +static int __init fsl_soc_dma_init(void)  { -	return snd_soc_register_platform(&fsl_soc_platform); +	pr_info("Freescale Elo DMA ASoC PCM Driver\n"); + +	return of_register_platform_driver(&fsl_soc_dma_driver);  } -module_init(fsl_soc_platform_init); -static void __exit fsl_soc_platform_exit(void) +static void __exit fsl_soc_dma_exit(void)  { -	snd_soc_unregister_platform(&fsl_soc_platform); +	of_unregister_platform_driver(&fsl_soc_dma_driver);  } -module_exit(fsl_soc_platform_exit); + +module_init(fsl_soc_dma_init); +module_exit(fsl_soc_dma_exit);  MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); -MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); -MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h index 385d4a42603c..78fee97e8036 100644 --- a/sound/soc/fsl/fsl_dma.h +++ b/sound/soc/fsl/fsl_dma.h @@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor {  	u8 res[4];      /* Reserved */  } __attribute__ ((aligned(32), packed)); -/* DMA information needed to create a snd_soc_dai object - * - * ssi_stx_phys: bus address of SSI STX register to use - * ssi_srx_phys: bus address of SSI SRX register to use - * dma[0]: points to the DMA channel to use for playback - * dma[1]: points to the DMA channel to use for capture - * dma_irq[0]: IRQ of the DMA channel to use for playback - * dma_irq[1]: IRQ of the DMA channel to use for capture - */ -struct fsl_dma_info { -	dma_addr_t ssi_stx_phys; -	dma_addr_t ssi_srx_phys; -	struct ccsr_dma_channel __iomem *dma_channel[2]; -	unsigned int dma_irq[2]; -}; - -extern struct snd_soc_platform fsl_soc_platform; - -int fsl_dma_configure(struct fsl_dma_info *dma_info); -  #endif diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 762c1b8e8e4e..7939c337ed9d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -3,10 +3,11 @@   *   * Author: Timur Tabi <timur@freescale.com>   * - * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed - * under the terms of the GNU General Public License version 2.  This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2.  This program is licensed "as is" without any warranty of any + * kind, whether express or implied.   */  #include <linux/init.h> @@ -15,6 +16,7 @@  #include <linux/device.h>  #include <linux/delay.h>  #include <linux/slab.h> +#include <linux/of_platform.h>  #include <sound/core.h>  #include <sound/pcm.h> @@ -22,8 +24,6 @@  #include <sound/initval.h>  #include <sound/soc.h> -#include <asm/immap_86xx.h> -  #include "fsl_ssi.h"  /** @@ -71,33 +71,31 @@  /**   * fsl_ssi_private: per-SSI private data   * - * @name: short name for this device ("SSI0", "SSI1", etc)   * @ssi: pointer to the SSI's registers   * @ssi_phys: physical address of the SSI registers   * @irq: IRQ of this SSI   * @first_stream: pointer to the stream that was opened first   * @second_stream: pointer to second stream - * @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 + * @name: name for this device   */  struct fsl_ssi_private { -	char name[8];  	struct ccsr_ssi __iomem *ssi;  	dma_addr_t ssi_phys;  	unsigned int irq;  	struct snd_pcm_substream *first_stream;  	struct snd_pcm_substream *second_stream; -	struct device *dev;  	unsigned int playback;  	unsigned int capture;  	int asynchronous; -	struct snd_soc_dai cpu_dai; +	struct snd_soc_dai_driver cpu_dai_drv;  	struct device_attribute dev_attr; +	struct platform_device *pdev;  	struct {  		unsigned int rfrc; @@ -122,6 +120,8 @@ struct fsl_ssi_private {  		unsigned int tfe1;  		unsigned int tfe0;  	} stats; + +	char name[1];  };  /** @@ -280,7 +280,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,  			   struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; +	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	/*  	 * If this is the first stream opened, then request the IRQ @@ -290,6 +290,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,  		struct ccsr_ssi __iomem *ssi = ssi_private->ssi;  		int ret; +		/* The 'name' should not have any slashes in it. */  		ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,  				  ssi_private->name, ssi_private);  		if (ret < 0) { @@ -422,7 +423,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,  static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,  	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)  { -	struct fsl_ssi_private *ssi_private = cpu_dai->private_data; +	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);  	if (substream == ssi_private->first_stream) {  		struct ccsr_ssi __iomem *ssi = ssi_private->ssi; @@ -458,7 +459,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,  			   struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; +	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;  	switch (cmd) { @@ -497,7 +498,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,  			     struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; +	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)  		ssi_private->playback--; @@ -523,56 +524,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,  	}  } -/** - * fsl_ssi_set_sysclk: set the clock frequency and direction - * - * This function is called by the machine driver to tell us what the clock - * frequency and direction are. - * - * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN), - * and we don't care about the frequency.  Return an error if the direction - * is not SND_SOC_CLOCK_IN. - * - * @clk_id: reserved, should be zero - * @freq: the frequency of the given clock ID, currently ignored - * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) - */ -static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai, -			      int clk_id, unsigned int freq, int dir) -{ - -	return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; -} - -/** - * fsl_ssi_set_fmt: set the serial format. - * - * This function is called by the machine driver to tell us what serial - * format to use. - * - * Currently, we only support I2S mode.  Return an error if the format is - * not SND_SOC_DAIFMT_I2S. - * - * @format: one of SND_SOC_DAIFMT_xxx - */ -static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) -{ -	return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; -} - -/** - * 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 = { +/* Template for the CPU dai driver structure */ +static struct snd_soc_dai_driver fsl_ssi_dai_template = {  	.playback = {  		/* The SSI does not support monaural audio. */  		.channels_min = 2, @@ -640,95 +600,186 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,  }  /** - * fsl_ssi_create_dai: create a snd_soc_dai structure - * - * This function is called by the machine driver to create a snd_soc_dai - * structure.  The function creates an ssi_private object, which contains - * the snd_soc_dai.  It also creates the sysfs statistics device. + * Make every character in a string lower-case   */ -struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) +static void make_lowercase(char *s) +{ +	char *p = s; +	char c; + +	while ((c = *p)) { +		if ((c >= 'A') && (c <= 'Z')) +			*p = c + ('a' - 'A'); +		p++; +	} +} + +static int __devinit fsl_ssi_probe(struct of_device *of_dev, +				   const struct of_device_id *match)  { -	struct snd_soc_dai *fsl_ssi_dai;  	struct fsl_ssi_private *ssi_private;  	int ret = 0; -	struct device_attribute *dev_attr; +	struct device_attribute *dev_attr = NULL; +	struct device_node *np = of_dev->dev.of_node; +	const char *p, *sprop; +	struct resource res; +	char name[64]; + +	/* SSIs that are not connected on the board should have a +	 *      status = "disabled" +	 * property in their device tree nodes. +	 */ +	if (!of_device_is_available(np)) +		return -ENODEV; + +	/* Check for a codec-handle property. */ +	if (!of_get_property(np, "codec-handle", NULL)) { +		dev_err(&of_dev->dev, "missing codec-handle property\n"); +		return -ENODEV; +	} + +	/* We only support the SSI in "I2S Slave" mode */ +	sprop = of_get_property(np, "fsl,mode", NULL); +	if (!sprop || strcmp(sprop, "i2s-slave")) { +		dev_notice(&of_dev->dev, "mode %s is unsupported\n", sprop); +		return -ENODEV; +	} -	ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL); +	/* The DAI name is the last part of the full name of the node. */ +	p = strrchr(np->full_name, '/') + 1; +	ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), +			      GFP_KERNEL);  	if (!ssi_private) { -		dev_err(ssi_info->dev, "could not allocate DAI object\n"); -		return NULL; +		dev_err(&of_dev->dev, "could not allocate DAI object\n"); +		return -ENOMEM;  	} -	memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template, -	       sizeof(struct snd_soc_dai)); -	fsl_ssi_dai = &ssi_private->cpu_dai; -	dev_attr = &ssi_private->dev_attr; +	strcpy(ssi_private->name, p); -	sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id); -	ssi_private->ssi = ssi_info->ssi; -	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; +	/* Initialize this copy of the CPU DAI driver structure */ +	memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, +	       sizeof(fsl_ssi_dai_template)); +	ssi_private->cpu_dai_drv.name = ssi_private->name; + +	/* Get the addresses and IRQ */ +	ret = of_address_to_resource(np, 0, &res); +	if (ret) { +		dev_err(&of_dev->dev, "could not determine device resources\n"); +		kfree(ssi_private); +		return ret; +	} +	ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start); +	ssi_private->ssi_phys = res.start; +	ssi_private->irq = irq_of_parse_and_map(np, 0); -	dev_set_drvdata(ssi_private->dev, fsl_ssi_dai); +	/* Are the RX and the TX clocks locked? */ +	if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) +		ssi_private->asynchronous = 1; +	else +		ssi_private->cpu_dai_drv.symmetric_rates = 1;  	/* Initialize the the device_attribute structure */ -	dev_attr->attr.name = "ssi-stats"; +	dev_attr = &ssi_private->dev_attr; +	dev_attr->attr.name = "statistics";  	dev_attr->attr.mode = S_IRUGO;  	dev_attr->show = fsl_sysfs_ssi_show; -	ret = device_create_file(ssi_private->dev, dev_attr); +	ret = device_create_file(&of_dev->dev, dev_attr);  	if (ret) { -		dev_err(ssi_info->dev, "could not create sysfs %s file\n", +		dev_err(&of_dev->dev, "could not create sysfs %s file\n",  			ssi_private->dev_attr.attr.name); -		kfree(fsl_ssi_dai); -		return NULL; +		goto error;  	} -	fsl_ssi_dai->private_data = ssi_private; -	fsl_ssi_dai->name = ssi_private->name; -	fsl_ssi_dai->id = ssi_info->id; -	fsl_ssi_dai->dev = ssi_info->dev; -	fsl_ssi_dai->symmetric_rates = 1; +	/* Register with ASoC */ +	dev_set_drvdata(&of_dev->dev, ssi_private); + +	ret = snd_soc_register_dai(&of_dev->dev, &ssi_private->cpu_dai_drv); +	if (ret) { +		dev_err(&of_dev->dev, "failed to register DAI: %d\n", ret); +		goto error; +	} -	ret = snd_soc_register_dai(fsl_ssi_dai); -	if (ret != 0) { -		dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); -		kfree(fsl_ssi_dai); -		return NULL; +	/* Trigger the machine driver's probe function.  The platform driver +	 * name of the machine driver is taken from the /model property of the +	 * device tree.  We also pass the address of the CPU DAI driver +	 * structure. +	 */ +	sprop = of_get_property(of_find_node_by_path("/"), "model", NULL); +	/* Sometimes the model name has a "fsl," prefix, so we strip that. */ +	p = strrchr(sprop, ','); +	if (p) +		sprop = p + 1; +	snprintf(name, sizeof(name), "snd-soc-%s", sprop); +	make_lowercase(name); + +	ssi_private->pdev = +		platform_device_register_data(&of_dev->dev, name, 0, NULL, 0); +	if (IS_ERR(ssi_private->pdev)) { +		ret = PTR_ERR(ssi_private->pdev); +		dev_err(&of_dev->dev, "failed to register platform: %d\n", ret); +		goto error;  	} -	return fsl_ssi_dai; +	return 0; + +error: +	snd_soc_unregister_dai(&of_dev->dev); +	dev_set_drvdata(&of_dev->dev, NULL); +	if (dev_attr) +		device_remove_file(&of_dev->dev, dev_attr); +	irq_dispose_mapping(ssi_private->irq); +	iounmap(ssi_private->ssi); +	kfree(ssi_private); + +	return ret;  } -EXPORT_SYMBOL_GPL(fsl_ssi_create_dai); -/** - * fsl_ssi_destroy_dai: destroy the snd_soc_dai object - * - * This function undoes the operations of fsl_ssi_create_dai() - */ -void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) +static int fsl_ssi_remove(struct of_device *of_dev)  { -	struct fsl_ssi_private *ssi_private = -	container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai); - -	device_remove_file(ssi_private->dev, &ssi_private->dev_attr); +	struct fsl_ssi_private *ssi_private = dev_get_drvdata(&of_dev->dev); -	snd_soc_unregister_dai(&ssi_private->cpu_dai); +	platform_device_unregister(ssi_private->pdev); +	snd_soc_unregister_dai(&of_dev->dev); +	device_remove_file(&of_dev->dev, &ssi_private->dev_attr);  	kfree(ssi_private); +	dev_set_drvdata(&of_dev->dev, NULL); + +	return 0;  } -EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); + +static const struct of_device_id fsl_ssi_ids[] = { +	{ .compatible = "fsl,mpc8610-ssi", }, +	{} +}; +MODULE_DEVICE_TABLE(of, fsl_ssi_ids); + +static struct of_platform_driver fsl_ssi_driver = { +	.driver = { +		.name = "fsl-ssi-dai", +		.owner = THIS_MODULE, +		.of_match_table = fsl_ssi_ids, +	}, +	.probe = fsl_ssi_probe, +	.remove = fsl_ssi_remove, +};  static int __init fsl_ssi_init(void)  {  	printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); -	return 0; +	return of_register_platform_driver(&fsl_ssi_driver);  } + +static void __exit fsl_ssi_exit(void) +{ +	of_unregister_platform_driver(&fsl_ssi_driver); +} +  module_init(fsl_ssi_init); +module_exit(fsl_ssi_exit);  MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");  MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index eade01feaab6..217300029b5b 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h @@ -196,31 +196,5 @@ struct ccsr_ssi {  #define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)  #define CCSR_SSI_SOR_SYNRST 		0x00000001 -/* Instantiation data for an SSI interface - * - * This structure contains all the information that the the SSI driver needs - * to instantiate an SSI interface with ALSA.  The machine driver should - * create this structure, fill it in, call fsl_ssi_create_dai(), and then - * delete the structure. - * - * id: which SSI this is (0, 1, etc. ) - * ssi: pointer to the SSI's registers - * 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; -	struct ccsr_ssi __iomem *ssi; -	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); -void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai); -  #endif diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..dce6b551cd78 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -9,6 +9,8 @@  #include <linux/module.h>  #include <linux/of_device.h>  #include <linux/slab.h> +#include <linux/of_device.h> +#include <linux/of_platform.h>  #include <sound/soc.h> @@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream)  static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);  	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; @@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct psc_dma_stream *s;  	int rc; @@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)  static int psc_dma_close(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct psc_dma_stream *s;  	dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); @@ -264,7 +266,7 @@ static snd_pcm_uframes_t  psc_dma_pointer(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct psc_dma_stream *s;  	dma_addr_t count; @@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  			   struct snd_pcm *pcm)  {  	struct snd_soc_pcm_runtime *rtd = pcm->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	size_t size = psc_dma_hardware.buffer_bytes_max;  	int rc = 0; -	dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", +	dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",  		card, dai, pcm);  	if (!card->dev->dma_mask) @@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,  			goto capture_alloc_err;  	} -	if (rtd->socdev->card->codec->ac97) -		rtd->socdev->card->codec->ac97->private_data = psc_dma; +	if (rtd->codec->ac97) +		rtd->codec->ac97->private_data = psc_dma;  	return 0; @@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm)  	struct snd_pcm_substream *substream;  	int stream; -	dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm); +	dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm);  	for (stream = 0; stream < 2; stream++) {  		substream = pcm->streams[stream].substream; @@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm)  	}  } -struct snd_soc_platform mpc5200_audio_dma_platform = { -	.name		= "mpc5200-psc-audio", -	.pcm_ops	= &psc_dma_ops, +static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { +	.ops		= &psc_dma_ops,  	.pcm_new	= &psc_dma_new,  	.pcm_free	= &psc_dma_free,  }; -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); -int mpc5200_audio_dma_create(struct of_device *op) +static int mpc5200_hpcd_probe(struct of_device *op, +		const struct of_device_id *match)  {  	phys_addr_t fifo;  	struct psc_dma *psc_dma; @@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct of_device *op)  	dev_set_drvdata(&op->dev, psc_dma);  	/* Tell the ASoC OF helpers about it */ -	return snd_soc_register_platform(&mpc5200_audio_dma_platform); +	return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform);  out_irq:  	free_irq(psc_dma->irq, psc_dma);  	free_irq(psc_dma->capture.irq, &psc_dma->capture); @@ -486,15 +487,14 @@ out_unmap:  	iounmap(regs);  	return ret;  } -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -int mpc5200_audio_dma_destroy(struct of_device *op) +static int mpc5200_hpcd_remove(struct of_device *op)  {  	struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);  	dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); -	snd_soc_unregister_platform(&mpc5200_audio_dma_platform); +	snd_soc_unregister_platform(&op->dev);  	bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);  	bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); @@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct of_device *op)  	return 0;  } -EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); + +static struct of_device_id mpc5200_hpcd_match[] = { +	{ +		.compatible = "fsl,mpc5200-pcm", +	}, +	{} +}; +MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); + +static struct of_platform_driver mpc5200_hpcd_of_driver = { +	.owner		= THIS_MODULE, +	.name		= "mpc5200-pcm-audio", +	.match_table    = mpc5200_hpcd_match, +	.probe		= mpc5200_hpcd_probe, +	.remove		= mpc5200_hpcd_remove, +}; + +static int __init mpc5200_hpcd_init(void) +{ +	return of_register_platform_driver(&mpc5200_hpcd_of_driver); +} + +static void __exit mpc5200_hpcd_exit(void) +{ +	of_unregister_platform_driver(&mpc5200_hpcd_of_driver); +} + +module_init(mpc5200_hpcd_init); +module_exit(mpc5200_hpcd_exit);  MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");  MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b373fb9..7472531bc2a4 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)  	return &psc_dma->playback;  } -int mpc5200_audio_dma_create(struct of_device *op); -int mpc5200_audio_dma_destroy(struct of_device *op); - -extern struct snd_soc_platform mpc5200_audio_dma_platform; -  #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220bfb7e..11706c128c08 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -129,7 +129,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *cpu_dai)  { -	struct psc_dma *psc_dma = cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);  	struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);  	dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" @@ -152,7 +152,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *cpu_dai)  { -	struct psc_dma *psc_dma = cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);  	dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); @@ -167,8 +167,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,  static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,  							struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai);  	struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);  	switch (cmd) { @@ -193,10 +192,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,  	return 0;  } -static int psc_ac97_probe(struct platform_device *pdev, -					struct snd_soc_dai *cpu_dai) +static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)  { -	struct psc_dma *psc_dma = cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);  	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;  	/* Go */ @@ -223,9 +221,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = {  	.hw_params	= psc_ac97_hw_digital_params,  }; -struct snd_soc_dai psc_ac97_dai[] = { +static struct snd_soc_dai_driver psc_ac97_dai[] = {  { -	.name   = "AC97",  	.ac97_control = 1,  	.probe	= psc_ac97_probe,  	.playback = { @@ -243,7 +240,6 @@ struct snd_soc_dai psc_ac97_dai[] = {  	.ops = &psc_ac97_analog_ops,  },  { -	.name   = "SPDIF",  	.ac97_control = 1,  	.playback = {  		.channels_min   = 1, @@ -254,7 +250,6 @@ struct snd_soc_dai psc_ac97_dai[] = {  	},  	.ops = &psc_ac97_digital_ops,  } }; -EXPORT_SYMBOL_GPL(psc_ac97_dai); @@ -266,18 +261,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai);  static int __devinit psc_ac97_of_probe(struct of_device *op,  				      const struct of_device_id *match)  { -	int rc, i; +	int rc;  	struct snd_ac97 ac97;  	struct mpc52xx_psc __iomem *regs; -	rc = mpc5200_audio_dma_create(op); -	if (rc != 0) -		return rc; - -	for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) -		psc_ac97_dai[i].dev = &op->dev; - -	rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); +	rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));  	if (rc != 0) {  		dev_err(&op->dev, "Failed to register DAI\n");  		return rc; @@ -287,9 +275,6 @@ static int __devinit psc_ac97_of_probe(struct of_device *op,  	regs = psc_dma->psc_regs;  	ac97.private_data = psc_dma; -	for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) -		psc_ac97_dai[i].private_data = psc_dma; -  	psc_dma->imr = 0;  	out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); @@ -305,7 +290,8 @@ static int __devinit psc_ac97_of_probe(struct of_device *op,  static int __devexit psc_ac97_of_remove(struct of_device *op)  { -	return mpc5200_audio_dma_destroy(op); +	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); +	return 0;  }  /* Match table for of_platform binding */ diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h index 4bc18c35c369..e881e784b270 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.h +++ b/sound/soc/fsl/mpc5200_psc_ac97.h @@ -7,8 +7,6 @@  #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__  #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ -extern struct snd_soc_dai psc_ac97_dai[]; -  #define MPC5200_AC97_NORMAL 0  #define MPC5200_AC97_SPDIF 1 diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 676841cbae98..5b9f2c73f031 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,  				 struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	u32 mode;  	dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" @@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,  static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,  			      int clk_id, unsigned int freq, int dir)  { -	struct psc_dma *psc_dma = cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);  	dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",  				cpu_dai, dir);  	return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; @@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,   */  static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)  { -	struct psc_dma *psc_dma = cpu_dai->private_data; +	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);  	dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",  				cpu_dai, format);  	return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; @@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = {  	.set_fmt	= psc_i2s_set_fmt,  }; -struct snd_soc_dai psc_i2s_dai[] = {{ -	.name   = "I2S", +static struct snd_soc_dai_driver psc_i2s_dai[] = {{  	.playback = {  		.channels_min = 2,  		.channels_max = 2, @@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{  	},  	.ops = &psc_i2s_dai_ops,  } }; -EXPORT_SYMBOL_GPL(psc_i2s_dai);  /* ---------------------------------------------------------------------   * OF platform bus binding code: @@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,  	struct psc_dma *psc_dma;  	struct mpc52xx_psc __iomem *regs; -	rc = mpc5200_audio_dma_create(op); -	if (rc != 0) -		return rc; - -	rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); +	rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));  	if (rc != 0) {  		pr_err("Failed to register DAI\n");  		return 0; @@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,  static int __devexit psc_i2s_of_remove(struct of_device *op)  { -	return mpc5200_audio_dma_destroy(op); +	snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); +	return 0;  }  /* Match table for of_platform binding */ diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 6a2764ee8203..38339c158ed9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -1,85 +1,96 @@  /** - * Freescale MPC8610HPCD ALSA SoC Fabric driver + * Freescale MPC8610HPCD ALSA SoC Machine driver   *   * Author: Timur Tabi <timur@freescale.com>   * - * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed - * under the terms of the GNU General Public License version 2.  This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. + * Copyright 2007-2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2.  This program is licensed "as is" without any warranty of any + * kind, whether express or implied.   */ -#include <linux/slab.h>  #include <linux/module.h>  #include <linux/interrupt.h>  #include <linux/of_device.h> -#include <linux/of_platform.h>  #include <sound/soc.h> -#include <asm/immap_86xx.h> +#include <asm/fsl_guts.h> -#include "../codecs/cs4270.h"  #include "fsl_dma.h"  #include "fsl_ssi.h" +/* There's only one global utilities register */ +static phys_addr_t guts_phys; + +#define DAI_NAME_SIZE	32 +  /** - * mpc8610_hpcd_data: fabric-specific ASoC device data + * mpc8610_hpcd_data: machine-specific ASoC device data   *   * This structure contains data for a single sound platform device on an   * MPC8610 HPCD.  Some of the data is taken from the device tree.   */  struct mpc8610_hpcd_data { -	struct snd_soc_device sound_devdata; -	struct snd_soc_dai_link dai; -	struct snd_soc_card machine; +	struct snd_soc_dai_link dai[2]; +	struct snd_soc_card card;  	unsigned int dai_format;  	unsigned int codec_clk_direction;  	unsigned int cpu_clk_direction;  	unsigned int clk_frequency; -	struct ccsr_guts __iomem *guts; -	struct ccsr_ssi __iomem *ssi; -	unsigned int ssi_id;    	/* 0 = SSI1, 1 = SSI2, etc */ -	unsigned int ssi_irq; -	unsigned int dma_id;    	/* 0 = DMA1, 1 = DMA2, etc */ -	unsigned int dma_irq[2]; -	struct ccsr_dma_channel __iomem *dma[2]; +	unsigned int ssi_id;		/* 0 = SSI1, 1 = SSI2, etc */ +	unsigned int dma_id[2];		/* 0 = DMA1, 1 = DMA2, etc */  	unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ +	char codec_dai_name[DAI_NAME_SIZE]; +	char codec_name[DAI_NAME_SIZE]; +	char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */  };  /** - * mpc8610_hpcd_machine_probe: initalize the board + * mpc8610_hpcd_machine_probe: initialize the board   * - * This function is called when platform_device_add() is called.  It is used - * to initialize the board-specific hardware. + * This function is used to initialize the board-specific hardware.   *   * Here we program the DMACR and PMUXCR registers.   */  static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)  { +	struct snd_soc_card *card = platform_get_drvdata(sound_device);  	struct mpc8610_hpcd_data *machine_data = -		sound_device->dev.platform_data; +		container_of(card, struct mpc8610_hpcd_data, card); +	struct ccsr_guts_86xx __iomem *guts; -	/* Program the signal routing between the SSI and the DMA */ -	guts_set_dmacr(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); -	guts_set_dmacr(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); +	guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); +	if (!guts) { +		dev_err(card->dev, "could not map global utilities\n"); +		return -ENOMEM; +	} -	guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[0], 0); -	guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[1], 0); +	/* Program the signal routing between the SSI and the DMA */ +	guts_set_dmacr(guts, machine_data->dma_id[0], +		       machine_data->dma_channel_id[0], +		       CCSR_GUTS_DMACR_DEV_SSI); +	guts_set_dmacr(guts, machine_data->dma_id[1], +		       machine_data->dma_channel_id[1], +		       CCSR_GUTS_DMACR_DEV_SSI); + +	guts_set_pmuxcr_dma(guts, machine_data->dma_id[0], +			    machine_data->dma_channel_id[0], 0); +	guts_set_pmuxcr_dma(guts, machine_data->dma_id[1], +			    machine_data->dma_channel_id[1], 0);  	switch (machine_data->ssi_id) {  	case 0: -		clrsetbits_be32(&machine_data->guts->pmuxcr, +		clrsetbits_be32(&guts->pmuxcr,  			CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI);  		break;  	case 1: -		clrsetbits_be32(&machine_data->guts->pmuxcr, +		clrsetbits_be32(&guts->pmuxcr,  			CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI);  		break;  	} +	iounmap(guts); +  	return 0;  } @@ -93,38 +104,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)  static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)  {  	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 mpc8610_hpcd_data *machine_data = -		rtd->socdev->dev->platform_data; +		container_of(rtd->card, struct mpc8610_hpcd_data, card); +	struct device *dev = rtd->card->dev;  	int ret = 0; -	/* Tell the CPU driver what the serial protocol is. */ -	ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format); -	if (ret < 0) { -		dev_err(substream->pcm->card->dev, -			"could not set CPU driver audio format\n"); -		return ret; -	} -  	/* Tell the codec driver what the serial protocol is. */ -	ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format); +	ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format);  	if (ret < 0) { -		dev_err(substream->pcm->card->dev, -			"could not set codec driver audio format\n"); -		return ret; -	} - -	/* -	 * Tell the CPU driver what the clock frequency is, and whether it's a -	 * slave or master. -	 */ -	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, -					machine_data->clk_frequency, -					machine_data->cpu_clk_direction); -	if (ret < 0) { -		dev_err(substream->pcm->card->dev, -			"could not set CPU driver clock parameters\n"); +		dev_err(dev, "could not set codec driver audio format\n");  		return ret;  	} @@ -132,12 +120,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)  	 * Tell the codec driver what the MCLK frequency is, and whether it's  	 * a slave or master.  	 */ -	ret = snd_soc_dai_set_sysclk(codec_dai, 0, -					machine_data->clk_frequency, -					machine_data->codec_clk_direction); +	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, +				     machine_data->clk_frequency, +				     machine_data->codec_clk_direction);  	if (ret < 0) { -		dev_err(substream->pcm->card->dev, -			"could not set codec driver clock params\n"); +		dev_err(dev, "could not set codec driver clock params\n");  		return ret;  	} @@ -150,116 +137,254 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)   * This function is called to remove the sound device for one SSI.  We   * de-program the DMACR and PMUXCR register.   */ -int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) +static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)  { +	struct snd_soc_card *card = platform_get_drvdata(sound_device);  	struct mpc8610_hpcd_data *machine_data = -		sound_device->dev.platform_data; +		container_of(card, struct mpc8610_hpcd_data, card); +	struct ccsr_guts_86xx __iomem *guts; + +	guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx)); +	if (!guts) { +		dev_err(card->dev, "could not map global utilities\n"); +		return -ENOMEM; +	}  	/* Restore the signal routing */ -	guts_set_dmacr(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[0], 0); -	guts_set_dmacr(machine_data->guts, machine_data->dma_id, -		machine_data->dma_channel_id[1], 0); +	guts_set_dmacr(guts, machine_data->dma_id[0], +		       machine_data->dma_channel_id[0], 0); +	guts_set_dmacr(guts, machine_data->dma_id[1], +		       machine_data->dma_channel_id[1], 0);  	switch (machine_data->ssi_id) {  	case 0: -		clrsetbits_be32(&machine_data->guts->pmuxcr, +		clrsetbits_be32(&guts->pmuxcr,  			CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);  		break;  	case 1: -		clrsetbits_be32(&machine_data->guts->pmuxcr, +		clrsetbits_be32(&guts->pmuxcr,  			CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);  		break;  	} +	iounmap(guts); +  	return 0;  }  /** - * mpc8610_hpcd_ops: ASoC fabric driver operations + * mpc8610_hpcd_ops: ASoC machine driver operations   */  static struct snd_soc_ops mpc8610_hpcd_ops = {  	.startup = mpc8610_hpcd_startup,  };  /** - * mpc8610_hpcd_probe: OF probe function for the fabric driver + * get_node_by_phandle_name - get a node by its phandle name   * - * This function gets called when an SSI node is found in the device tree. + * This function takes a node, the name of a property in that node, and a + * compatible string.  Assuming the property is a phandle to another node, + * it returns that node, (optionally) if that node is compatible.   * - * Although this is a fabric driver, the SSI node is the "master" node with - * respect to audio hardware connections.  Therefore, we create a new ASoC - * device for each new SSI node that has a codec attached. + * If the property is not a phandle, or the node it points to is not compatible + * with the specific string, then NULL is returned. + */ +static struct device_node *get_node_by_phandle_name(struct device_node *np, +					       const char *name, +					       const char *compatible) +{ +	const phandle *ph; +	int len; + +	ph = of_get_property(np, name, &len); +	if (!ph || (len != sizeof(phandle))) +		return NULL; + +	np = of_find_node_by_phandle(*ph); +	if (!np) +		return NULL; + +	if (compatible && !of_device_is_compatible(np, compatible)) { +		of_node_put(np); +		return NULL; +	} + +	return np; +} + +/** + * get_parent_cell_index -- return the cell-index of the parent of a node   * - * FIXME: Currently, we only support one DMA controller, so if there are - * multiple SSI nodes with codecs, only the first will be supported. + * Return the value of the cell-index property of the parent of the given + * node.  This is used for DMA channel nodes that need to know the DMA ID + * of the controller they are on. + */ +static int get_parent_cell_index(struct device_node *np) +{ +	struct device_node *parent = of_get_parent(np); +	const u32 *iprop; + +	if (!parent) +		return -1; + +	iprop = of_get_property(parent, "cell-index", NULL); +	of_node_put(parent); + +	if (!iprop) +		return -1; + +	return *iprop; +} + +/** + * codec_node_dev_name - determine the dev_name for a codec node + * + * This function determines the dev_name for an I2C node.  This is the name + * that would be returned by dev_name() if this device_node were part of a + * 'struct device'  It's ugly and hackish, but it works.   * - * FIXME: Even if we did support multiple DMA controllers, we have no - * mechanism for assigning DMA controllers and channels to the individual - * SSI devices.  We also probably aren't compatible with the generic Elo DMA - * device driver. + * The dev_name for such devices include the bus number and I2C address. For + * example, "cs4270-codec.0-004f".   */ -static int mpc8610_hpcd_probe(struct of_device *ofdev, -	const struct of_device_id *match) +static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)  { -	struct device_node *np = ofdev->dev.of_node; -	struct device_node *codec_np = NULL; -	struct device_node *guts_np = NULL; -	struct device_node *dma_np = NULL; -	struct device_node *dma_channel_np = NULL; -	const phandle *codec_ph; -	const char *sprop;  	const u32 *iprop; +	int bus, addr; +	char temp[DAI_NAME_SIZE]; + +	of_modalias_node(np, temp, DAI_NAME_SIZE); + +	iprop = of_get_property(np, "reg", NULL); +	if (!iprop) +		return -EINVAL; + +	addr = *iprop; + +	bus = get_parent_cell_index(np); +	if (bus < 0) +		return bus; + +	snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr); + +	return 0; +} + +static int get_dma_channel(struct device_node *ssi_np, +			   const char *compatible, +			   struct snd_soc_dai_link *dai, +			   unsigned int *dma_channel_id, +			   unsigned int *dma_id) +{  	struct resource res; +	struct device_node *dma_channel_np; +	const u32 *iprop; +	int ret; + +	dma_channel_np = get_node_by_phandle_name(ssi_np, compatible, +						  "fsl,ssi-dma-channel"); +	if (!dma_channel_np) +		return -EINVAL; + +	/* Determine the dev_name for the device_node.  This code mimics the +	 * behavior of of_device_make_bus_id(). We need this because ASoC uses +	 * the dev_name() of the device to match the platform (DMA) device with +	 * the CPU (SSI) device.  It's all ugly and hackish, but it works (for +	 * now). +	 * +	 * dai->platform name should already point to an allocated buffer. +	 */ +	ret = of_address_to_resource(dma_channel_np, 0, &res); +	if (ret) +		return ret; +	snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", +		 (unsigned long long) res.start, dma_channel_np->name); + +	iprop = of_get_property(dma_channel_np, "cell-index", NULL); +	if (!iprop) { +		of_node_put(dma_channel_np); +		return -EINVAL; +	} + +	*dma_channel_id = *iprop; +	*dma_id = get_parent_cell_index(dma_channel_np); +	of_node_put(dma_channel_np); + +	return 0; +} + +/** + * mpc8610_hpcd_probe: platform probe function for the machine driver + * + * Although this is a machine driver, the SSI node is the "master" node with + * respect to audio hardware connections.  Therefore, we create a new ASoC + * device for each new SSI node that has a codec attached. + */ +static int mpc8610_hpcd_probe(struct platform_device *pdev) +{ +	struct device *dev = pdev->dev.parent; +	/* of_dev is the OF device for the SSI node that probed us */ +	struct of_device *of_dev = container_of(dev, struct of_device, dev); +	struct device_node *np = of_dev->dev.of_node; +	struct device_node *codec_np = NULL;  	struct platform_device *sound_device = NULL;  	struct mpc8610_hpcd_data *machine_data; -	struct fsl_ssi_info ssi_info; -	struct fsl_dma_info dma_info;  	int ret = -ENODEV; -	unsigned int playback_dma_channel; -	unsigned int capture_dma_channel; +	const char *sprop; +	const u32 *iprop; + +	/* We are only interested in SSIs with a codec phandle in them, +	 * so let's make sure this SSI has one. The MPC8610 HPCD only +	 * knows about the CS4270 codec, so reject anything else. +	 */ +	codec_np = get_node_by_phandle_name(np, "codec-handle", +					    "cirrus,cs4270"); +	if (!codec_np) { +		dev_err(dev, "invalid codec node\n"); +		return -EINVAL; +	}  	machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);  	if (!machine_data)  		return -ENOMEM; -	memset(&ssi_info, 0, sizeof(ssi_info)); -	memset(&dma_info, 0, sizeof(dma_info)); - -	ssi_info.dev = &ofdev->dev; +	machine_data->dai[0].cpu_dai_name = dev_name(&of_dev->dev); +	machine_data->dai[0].ops = &mpc8610_hpcd_ops; -	/* -	 * We are only interested in SSIs with a codec phandle in them, so let's -	 * make sure this SSI has one. -	 */ -	codec_ph = of_get_property(np, "codec-handle", NULL); -	if (!codec_ph) +	/* Determine the codec name, it will be used as the codec DAI name */ +	ret = codec_node_dev_name(codec_np, machine_data->codec_name, +				  DAI_NAME_SIZE); +	if (ret) { +		dev_err(&pdev->dev, "invalid codec node %s\n", +			codec_np->full_name); +		ret = -EINVAL;  		goto error; +	} +	machine_data->dai[0].codec_name = machine_data->codec_name; -	codec_np = of_find_node_by_phandle(*codec_ph); -	if (!codec_np) -		goto error; +	/* The DAI name from the codec (snd_soc_dai_driver.name) */ +	machine_data->dai[0].codec_dai_name = "cs4270-hifi"; -	/* The MPC8610 HPCD only knows about the CS4270 codec, so reject -	   anything else. */ -	if (!of_device_is_compatible(codec_np, "cirrus,cs4270")) -		goto error; +	/* We register two DAIs per SSI, one for playback and the other for +	 * capture.  Currently, we only support codecs that have one DAI for +	 * both playback and capture. +	 */ +	memcpy(&machine_data->dai[1], &machine_data->dai[0], +	       sizeof(struct snd_soc_dai_link));  	/* Get the device ID */  	iprop = of_get_property(np, "cell-index", NULL);  	if (!iprop) { -		dev_err(&ofdev->dev, "cell-index property not found\n"); +		dev_err(&pdev->dev, "cell-index property not found\n");  		ret = -EINVAL;  		goto error;  	}  	machine_data->ssi_id = *iprop; -	ssi_info.id = *iprop;  	/* Get the serial format and clock direction. */  	sprop = of_get_property(np, "fsl,mode", NULL);  	if (!sprop) { -		dev_err(&ofdev->dev, "fsl,mode property not found\n"); +		dev_err(&pdev->dev, "fsl,mode property not found\n");  		ret = -EINVAL;  		goto error;  	} @@ -269,15 +394,14 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,  		machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; -		/* -		 * In i2s-slave mode, the codec has its own clock source, so we +		/* In i2s-slave mode, the codec has its own clock source, so we  		 * need to get the frequency from the device tree and pass it to  		 * the codec driver.  		 */  		iprop = of_get_property(codec_np, "clock-frequency", NULL);  		if (!iprop || !*iprop) { -			dev_err(&ofdev->dev, "codec bus-frequency property " -				"is missing or invalid\n"); +			dev_err(&pdev->dev, "codec bus-frequency " +				"property is missing or invalid\n");  			ret = -EINVAL;  			goto error;  		} @@ -311,317 +435,153 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,  		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;  	} else { -		dev_err(&ofdev->dev, -			"unrecognized fsl,mode property \"%s\"\n", sprop); +		dev_err(&pdev->dev, +			"unrecognized fsl,mode property '%s'\n", sprop);  		ret = -EINVAL;  		goto error;  	}  	if (!machine_data->clk_frequency) { -		dev_err(&ofdev->dev, "unknown clock frequency\n"); +		dev_err(&pdev->dev, "unknown clock frequency\n");  		ret = -EINVAL;  		goto error;  	} -	/* Read the SSI information from the device tree */ -	ret = of_address_to_resource(np, 0, &res); +	/* Find the playback DMA channel to use. */ +	machine_data->dai[0].platform_name = machine_data->platform_name[0]; +	ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], +			      &machine_data->dma_channel_id[0], +			      &machine_data->dma_id[0]);  	if (ret) { -		dev_err(&ofdev->dev, "could not obtain SSI address\n"); -		goto error; -	} -	if (!res.start) { -		dev_err(&ofdev->dev, "invalid SSI address\n"); -		goto error; -	} -	ssi_info.ssi_phys = res.start; - -	machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi)); -	if (!machine_data->ssi) { -		dev_err(&ofdev->dev, "could not map SSI address %x\n", -			ssi_info.ssi_phys); -		ret = -EINVAL; +		dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");  		goto error;  	} -	ssi_info.ssi = machine_data->ssi; - -	/* Get the IRQ of the SSI */ -	machine_data->ssi_irq = irq_of_parse_and_map(np, 0); -	if (!machine_data->ssi_irq) { -		dev_err(&ofdev->dev, "could not get SSI IRQ\n"); -		ret = -EINVAL; -		goto error; -	} -	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"); -	if (!guts_np) { -		dev_err(&ofdev->dev, "could not obtain address of GUTS\n"); -		ret = -EINVAL; -		goto error; -	} -	machine_data->guts = of_iomap(guts_np, 0); -	of_node_put(guts_np); -	if (!machine_data->guts) { -		dev_err(&ofdev->dev, "could not map GUTS\n"); -		ret = -EINVAL; -		goto error; -	} - -	/* Find the DMA channels to use.  Both SSIs need to use the same DMA -	 * controller, so let's use DMA#1. -	 */ -	for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") { -		iprop = of_get_property(dma_np, "cell-index", NULL); -		if (iprop && (*iprop == 0)) { -			of_node_put(dma_np); -			break; -		} -	} -	if (!dma_np) { -		dev_err(&ofdev->dev, "could not find DMA node\n"); -		ret = -EINVAL; -		goto error; -	} -	machine_data->dma_id = *iprop; - -	/* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA -	 * channels 2 and 3.  This is just how the MPC8610 is wired -	 * internally. -	 */ -	playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2; -	capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3; - -	/* -	 * Find the DMA channels to use. -	 */ -	while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) { -		iprop = of_get_property(dma_channel_np, "cell-index", NULL); -		if (iprop && (*iprop == playback_dma_channel)) { -			/* dma_channel[0] and dma_irq[0] are for playback */ -			dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0); -			dma_info.dma_irq[0] = -				irq_of_parse_and_map(dma_channel_np, 0); -			machine_data->dma_channel_id[0] = *iprop; -			continue; -		} -		if (iprop && (*iprop == capture_dma_channel)) { -			/* dma_channel[1] and dma_irq[1] are for capture */ -			dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0); -			dma_info.dma_irq[1] = -				irq_of_parse_and_map(dma_channel_np, 0); -			machine_data->dma_channel_id[1] = *iprop; -			continue; -		} -	} -	if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] || -	    !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) { -		dev_err(&ofdev->dev, "could not find DMA channels\n"); -		ret = -EINVAL; +	/* Find the capture DMA channel to use. */ +	machine_data->dai[1].platform_name = machine_data->platform_name[1]; +	ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], +			      &machine_data->dma_channel_id[1], +			      &machine_data->dma_id[1]); +	if (ret) { +		dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");  		goto error;  	} -	dma_info.ssi_stx_phys = ssi_info.ssi_phys + -		offsetof(struct ccsr_ssi, stx0); -	dma_info.ssi_srx_phys = ssi_info.ssi_phys + -		offsetof(struct ccsr_ssi, srx0); - -	/* We have the DMA information, so tell the DMA driver what it is */ -	if (!fsl_dma_configure(&dma_info)) { -		dev_err(&ofdev->dev, "could not instantiate DMA device\n"); -		ret = -EBUSY; -		goto error; -	} +	/* Initialize our DAI data structure.  */ +	machine_data->dai[0].stream_name = "playback"; +	machine_data->dai[1].stream_name = "capture"; +	machine_data->dai[0].name = machine_data->dai[0].stream_name; +	machine_data->dai[1].name = machine_data->dai[1].stream_name; -	/* -	 * Initialize our DAI data structure.  We should probably get this -	 * information from the device tree. -	 */ -	machine_data->dai.name = "CS4270"; -	machine_data->dai.stream_name = "CS4270"; - -	machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info); -	machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */ -	machine_data->dai.ops = &mpc8610_hpcd_ops; - -	machine_data->machine.probe = mpc8610_hpcd_machine_probe; -	machine_data->machine.remove = mpc8610_hpcd_machine_remove; -	machine_data->machine.name = "MPC8610 HPCD"; -	machine_data->machine.num_links = 1; -	machine_data->machine.dai_link = &machine_data->dai; +	machine_data->card.probe = mpc8610_hpcd_machine_probe; +	machine_data->card.remove = mpc8610_hpcd_machine_remove; +	machine_data->card.name = pdev->name; /* The platform driver name */ +	machine_data->card.num_links = 2; +	machine_data->card.dai_link = machine_data->dai;  	/* Allocate a new audio platform device structure */  	sound_device = platform_device_alloc("soc-audio", -1);  	if (!sound_device) { -		dev_err(&ofdev->dev, "platform device allocation failed\n"); +		dev_err(&pdev->dev, "platform device alloc failed\n");  		ret = -ENOMEM;  		goto error;  	} -	machine_data->sound_devdata.card = &machine_data->machine; -	machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; -	machine_data->machine.platform = &fsl_soc_platform; - -	sound_device->dev.platform_data = machine_data; - - -	/* Set the platform device and ASoC device to point to each other */ -	platform_set_drvdata(sound_device, &machine_data->sound_devdata); +	/* Associate the card data with the sound device */ +	platform_set_drvdata(sound_device, &machine_data->card); -	machine_data->sound_devdata.dev = &sound_device->dev; - - -	/* Tell ASoC to probe us.  This will call mpc8610_hpcd_machine.probe(), -	   if it exists. */ +	/* Register with ASoC */  	ret = platform_device_add(sound_device); -  	if (ret) { -		dev_err(&ofdev->dev, "platform device add failed\n"); +		dev_err(&pdev->dev, "platform device add failed\n");  		goto error;  	} -	dev_set_drvdata(&ofdev->dev, sound_device); +	of_node_put(codec_np);  	return 0;  error:  	of_node_put(codec_np); -	of_node_put(guts_np); -	of_node_put(dma_np); -	of_node_put(dma_channel_np);  	if (sound_device)  		platform_device_unregister(sound_device); -	if (machine_data->dai.cpu_dai) -		fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); - -	if (ssi_info.ssi) -		iounmap(ssi_info.ssi); - -	if (ssi_info.irq) -		irq_dispose_mapping(ssi_info.irq); - -	if (dma_info.dma_channel[0]) -		iounmap(dma_info.dma_channel[0]); - -	if (dma_info.dma_channel[1]) -		iounmap(dma_info.dma_channel[1]); - -	if (dma_info.dma_irq[0]) -		irq_dispose_mapping(dma_info.dma_irq[0]); - -	if (dma_info.dma_irq[1]) -		irq_dispose_mapping(dma_info.dma_irq[1]); - -	if (machine_data->guts) -		iounmap(machine_data->guts); -  	kfree(machine_data);  	return ret;  }  /** - * mpc8610_hpcd_remove: remove the OF device + * mpc8610_hpcd_remove: remove the platform device   * - * This function is called when the OF device is removed. + * This function is called when the platform device is removed.   */ -static int mpc8610_hpcd_remove(struct of_device *ofdev) +static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)  { -	struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); +	struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); +	struct snd_soc_card *card = platform_get_drvdata(sound_device);  	struct mpc8610_hpcd_data *machine_data = -		sound_device->dev.platform_data; +		container_of(card, struct mpc8610_hpcd_data, card);  	platform_device_unregister(sound_device); -	if (machine_data->dai.cpu_dai) -		fsl_ssi_destroy_dai(machine_data->dai.cpu_dai); - -	if (machine_data->ssi) -		iounmap(machine_data->ssi); - -	if (machine_data->dma[0]) -		iounmap(machine_data->dma[0]); - -	if (machine_data->dma[1]) -		iounmap(machine_data->dma[1]); - -	if (machine_data->dma_irq[0]) -		irq_dispose_mapping(machine_data->dma_irq[0]); - -	if (machine_data->dma_irq[1]) -		irq_dispose_mapping(machine_data->dma_irq[1]); - -	if (machine_data->guts) -		iounmap(machine_data->guts); -  	kfree(machine_data);  	sound_device->dev.platform_data = NULL; -	dev_set_drvdata(&ofdev->dev, NULL); +	dev_set_drvdata(&pdev->dev, NULL);  	return 0;  } -static struct of_device_id mpc8610_hpcd_match[] = { -	{ -		.compatible = "fsl,mpc8610-ssi", -	}, -	{} -}; -MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match); - -static struct of_platform_driver mpc8610_hpcd_of_driver = { +static struct platform_driver mpc8610_hpcd_driver = { +	.probe = mpc8610_hpcd_probe, +	.remove = __devexit_p(mpc8610_hpcd_remove),  	.driver = { -		.name = "mpc8610_hpcd", +		/* The name must match the 'model' property in the device tree, +		 * in lowercase letters. +		 */ +		.name = "snd-soc-mpc8610hpcd",  		.owner = THIS_MODULE, -		.of_match_table = mpc8610_hpcd_match,  	}, -	.probe  	= mpc8610_hpcd_probe, -	.remove 	= mpc8610_hpcd_remove,  };  /** - * mpc8610_hpcd_init: fabric driver initialization. + * mpc8610_hpcd_init: machine driver initialization.   *   * This function is called when this module is loaded.   */  static int __init mpc8610_hpcd_init(void)  { -	int ret; - -	printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n"); +	struct device_node *guts_np; +	struct resource res; -	ret = of_register_platform_driver(&mpc8610_hpcd_of_driver); +	pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n"); -	if (ret) -		printk(KERN_ERR -			"mpc8610-hpcd: failed to register platform driver\n"); +	/* Get the physical address of the global utilities registers */ +	guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); +	if (of_address_to_resource(guts_np, 0, &res)) { +		pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); +		return -EINVAL; +	} +	guts_phys = res.start; -	return ret; +	return platform_driver_register(&mpc8610_hpcd_driver);  }  /** - * mpc8610_hpcd_exit: fabric driver exit + * mpc8610_hpcd_exit: machine driver exit   *   * This function is called when this driver is unloaded.   */  static void __exit mpc8610_hpcd_exit(void)  { -	of_unregister_platform_driver(&mpc8610_hpcd_of_driver); +	platform_driver_unregister(&mpc8610_hpcd_driver);  }  module_init(mpc8610_hpcd_init);  module_exit(mpc8610_hpcd_exit);  MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); -MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver"); -MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 6644cba7cbf2..fe15bb26e484 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -32,21 +32,24 @@  #define DRV_NAME "pcm030-audio-fabric" -static struct snd_soc_device device;  static struct snd_soc_card card;  static struct snd_soc_dai_link pcm030_fabric_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 Analog", -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], -	.cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], +	.codec_dai_name = "wm9712-hifi", +	.cpu_dai_name = "mpc5200-psc-ac97.0", +	.platform_name = "mpc5200-pcm-audio", +	.codec_name = "wm9712-codec",  },  {  	.name = "AC97",  	.stream_name = "AC97 IEC958", -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], -	.cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], +	.codec_dai_name = "wm9712-aux", +	.cpu_dai_name = "mpc5200-psc-ac97.1", +	.platform_name = "mpc5200-pcm-audio", +	..codec_name = "wm9712-codec",  },  }; @@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void)  	if (!of_machine_is_compatible("phytec,pcm030"))  		return -ENODEV; -	card.platform = &mpc5200_audio_dma_platform; +  	card.name = "pcm030";  	card.dai_link = pcm030_fabric_dai;  	card.num_links = ARRAY_SIZE(pcm030_fabric_dai); -	device.card = &card; -	device.codec_dev = &soc_codec_dev_wm9712; -  	pdev = platform_device_alloc("soc-audio", 1);  	if (!pdev) {  		pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");  		return -ENODEV;  	} -	platform_set_drvdata(pdev, &device); -	device.dev = &pdev->dev; +	platform_set_drvdata(pdev, &card);  	rc = platform_device_add(pdev);  	if (rc) { diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c deleted file mode 100644 index 3bc13fd89096..000000000000 --- a/sound/soc/fsl/soc-of-simple.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * OF helpers for ALSA SoC Layer - * - * Copyright (C) 2008, Secret Lab Technologies Ltd. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/pm.h> -#include <linux/bitops.h> -#include <linux/platform_device.h> -#include <linux/of.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/soc-of-simple.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings"); - -static DEFINE_MUTEX(of_snd_soc_mutex); -static LIST_HEAD(of_snd_soc_device_list); -static int of_snd_soc_next_index; - -struct of_snd_soc_device { -	int id; -	struct list_head list; -	struct snd_soc_device device; -	struct snd_soc_card card; -	struct snd_soc_dai_link dai_link; -	struct platform_device *pdev; -	struct device_node *platform_node; -	struct device_node *codec_node; -}; - -static struct snd_soc_ops of_snd_soc_ops = { -}; - -static struct of_snd_soc_device * -of_snd_soc_get_device(struct device_node *codec_node) -{ -	struct of_snd_soc_device *of_soc; - -	list_for_each_entry(of_soc, &of_snd_soc_device_list, list) { -		if (of_soc->codec_node == codec_node) -			return of_soc; -	} - -	of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL); -	if (!of_soc) -		return NULL; - -	/* Initialize the structure and add it to the global list */ -	of_soc->codec_node = codec_node; -	of_soc->id = of_snd_soc_next_index++; -	of_soc->card.dai_link = &of_soc->dai_link; -	of_soc->card.num_links = 1; -	of_soc->device.card = &of_soc->card; -	of_soc->dai_link.ops = &of_snd_soc_ops; -	list_add(&of_soc->list, &of_snd_soc_device_list); - -	return of_soc; -} - -static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc) -{ -	struct platform_device *pdev; -	int rc; - -	/* Only register the device if both the codec and platform have -	 * been registered */ -	if ((!of_soc->device.codec_data) || (!of_soc->platform_node)) -		return; - -	pr_info("platform<-->codec match achieved; registering machine\n"); - -	pdev = platform_device_alloc("soc-audio", of_soc->id); -	if (!pdev) { -		pr_err("of_soc: platform_device_alloc() failed\n"); -		return; -	} - -	pdev->dev.platform_data = of_soc; -	platform_set_drvdata(pdev, &of_soc->device); -	of_soc->device.dev = &pdev->dev; - -	/* The ASoC device is complete; register it */ -	rc = platform_device_add(pdev); -	if (rc) { -		pr_err("of_soc: platform_device_add() failed\n"); -		return; -	} - -} - -int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev, -			      void *codec_data, struct snd_soc_dai *dai, -			      struct device_node *node) -{ -	struct of_snd_soc_device *of_soc; -	int rc = 0; - -	pr_info("registering ASoC codec driver: %s\n", node->full_name); - -	mutex_lock(&of_snd_soc_mutex); -	of_soc = of_snd_soc_get_device(node); -	if (!of_soc) { -		rc = -ENOMEM; -		goto out; -	} - -	/* Store the codec data */ -	of_soc->device.codec_data = codec_data; -	of_soc->device.codec_dev = codec_dev; -	of_soc->dai_link.name = (char *)node->name; -	of_soc->dai_link.stream_name = (char *)node->name; -	of_soc->dai_link.codec_dai = dai; - -	/* Now try to register the SoC device */ -	of_snd_soc_register_device(of_soc); - - out: -	mutex_unlock(&of_snd_soc_mutex); -	return rc; -} -EXPORT_SYMBOL_GPL(of_snd_soc_register_codec); - -int of_snd_soc_register_platform(struct snd_soc_platform *platform, -				 struct device_node *node, -				 struct snd_soc_dai *cpu_dai) -{ -	struct of_snd_soc_device *of_soc; -	struct device_node *codec_node; -	const phandle *handle; -	int len, rc = 0; - -	pr_info("registering ASoC platform driver: %s\n", node->full_name); - -	handle = of_get_property(node, "codec-handle", &len); -	if (!handle || len < sizeof(handle)) -		return -ENODEV; -	codec_node = of_find_node_by_phandle(*handle); -	if (!codec_node) -		return -ENODEV; -	pr_info("looking for codec: %s\n", codec_node->full_name); - -	mutex_lock(&of_snd_soc_mutex); -	of_soc = of_snd_soc_get_device(codec_node); -	if (!of_soc) { -		rc = -ENOMEM; -		goto out; -	} - -	of_soc->platform_node = node; -	of_soc->dai_link.cpu_dai = cpu_dai; -	of_soc->card.platform = platform; -	of_soc->card.name = of_soc->dai_link.cpu_dai->name; - -	/* Now try to register the SoC device */ -	of_snd_soc_register_device(of_soc); - - out: -	mutex_unlock(&of_snd_soc_mutex); -	return rc; -} -EXPORT_SYMBOL_GPL(of_snd_soc_register_platform); diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 52dac5e3874c..66ba26393c10 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -8,12 +8,24 @@ menuconfig SND_IMX_SOC  	  Say Y or M if you want to add support for codecs attached to  	  the i.MX SSI interface. +  if SND_IMX_SOC +config SND_MXC_SOC_SSI +	tristate + +config SND_MXC_SOC_FIQ +	tristate + +config SND_MXC_SOC_MX2 +	tristate +  config SND_MXC_SOC_WM1133_EV1  	tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"  	depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL  	select SND_SOC_WM8350 +	select SND_MXC_SOC_SSI +	select SND_MXC_SOC_FIQ  	help  	  Enable support for audio on the i.MX31ADS with the WM1133-EV1  	  PMIC board with WM8835x fitted. @@ -22,6 +34,8 @@ config SND_SOC_PHYCORE_AC97  	tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"  	depends on MACH_PCM043 || MACH_PCA100  	select SND_SOC_WM9712 +	select SND_MXC_SOC_SSI +	select SND_MXC_SOC_FIQ  	help  	  Say Y if you want to add support for SoC audio on Phytec phyCORE  	  and phyCARD boards in AC97 mode @@ -30,6 +44,8 @@ config SND_SOC_EUKREA_TLV320  	tristate "Eukrea TLV320"  	depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD  	select SND_SOC_TLV320AIC23 +	select SND_MXC_SOC_SSI +	select SND_MXC_SOC_FIQ  	help  	  Enable I2S based access to the TLV320AIC23B codec attached  	  to the SSI interface diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 7bc57baf2b0e..b67fc02a4ecc 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -1,11 +1,11 @@  # i.MX Platform Support -snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o - -ifdef CONFIG_MACH_MX27 -snd-soc-imx-objs += imx-pcm-dma-mx2.o -endif +snd-soc-imx-objs := imx-ssi.o +snd-soc-imx-fiq-objs := imx-pcm-fiq.o +snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o  obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o +obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o +obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o  # i.MX Machine Support  snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index f15dfbdc47ee..807f736ee294 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -79,22 +79,19 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = {  static struct snd_soc_dai_link eukrea_tlv320_dai = {  	.name		= "tlv320aic23",  	.stream_name	= "TLV320AIC23", -	.codec_dai	= &tlv320aic23_dai, +	.codec_dai	= "tlv320aic23-hifi", +	.platform_name	= "imx-pcm-audio.0", +	.codec_name	= "tlv320aic23-codec.0-001a", +	.cpu_dai = "imx-ssi-dai.0",  	.ops		= &eukrea_tlv320_snd_ops,  };  static struct snd_soc_card eukrea_tlv320 = {  	.name		= "cpuimx-audio", -	.platform	= &imx_soc_platform,  	.dai_link	= &eukrea_tlv320_dai,  	.num_links	= 1,  }; -static struct snd_soc_device eukrea_tlv320_snd_devdata = { -	.card		= &eukrea_tlv320, -	.codec_dev	= &soc_codec_dev_tlv320aic23, -}; -  static struct platform_device *eukrea_tlv320_snd_device;  static int __init eukrea_tlv320_init(void) @@ -110,10 +107,7 @@ static int __init eukrea_tlv320_init(void)  	if (!eukrea_tlv320_snd_device)  		return -ENOMEM; -	eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0]; - -	platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata); -	eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev; +	platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320);  	ret = platform_device_add(eukrea_tlv320_snd_device);  	if (ret) { diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 0a595da4811d..fd493ee1428e 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -103,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)  	struct imx_pcm_runtime_data *iprtd = runtime->private_data;  	int ret; -	dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);  	if (iprtd->dma < 0) { @@ -213,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)  	struct imx_pcm_runtime_data *iprtd = runtime->private_data;  	int err; -	dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	iprtd->substream = substream;  	iprtd->buf = (unsigned int *)substream->dma_buffer.area; @@ -318,19 +318,42 @@ static struct snd_pcm_ops imx_pcm_ops = {  	.mmap		= snd_imx_pcm_mmap,  }; -static struct snd_soc_platform imx_soc_platform_dma = { -	.name		= "imx-audio", -	.pcm_ops 	= &imx_pcm_ops, +static struct snd_soc_platform_driver imx_soc_platform_mx2 = { +	.ops		= &imx_pcm_ops,  	.pcm_new	= imx_pcm_new,  	.pcm_free	= imx_pcm_free,  }; -struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, -		struct imx_ssi *ssi) +static int __devinit imx_soc_platform_probe(struct platform_device *pdev)  { -	ssi->dma_params_tx.burstsize = DMA_TXFIFO_BURST; -	ssi->dma_params_rx.burstsize = DMA_RXFIFO_BURST; +	return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); +} + +static int __devexit imx_soc_platform_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver imx_pcm_driver = { +	.driver = { +			.name = "imx-pcm-audio", +			.owner = THIS_MODULE, +	}, -	return &imx_soc_platform_dma; +	.probe = imx_soc_platform_probe, +	.remove = __devexit_p(imx_soc_platform_remove), +}; + +static int __init snd_imx_pcm_init(void) +{ +	return platform_driver_register(&imx_pcm_driver); +} +module_init(snd_imx_pcm_init); + +static void __exit snd_imx_pcm_exit(void) +{ +	platform_driver_unregister(&imx_pcm_driver);  } +module_exit(snd_imx_pcm_exit); diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index b2bf27282cd2..413b78da248f 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c @@ -236,6 +236,8 @@ static struct snd_pcm_ops imx_pcm_ops = {  	.mmap		= snd_imx_pcm_mmap,  }; +static int ssi_irq = 0; +  static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,  	struct snd_pcm *pcm)  { @@ -245,7 +247,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (ret)  		return ret; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		struct snd_pcm_substream *substream =  			pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;  		struct snd_dma_buffer *buf = &substream->dma_buffer; @@ -253,7 +255,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,  		imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		struct snd_pcm_substream *substream =  			pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;  		struct snd_dma_buffer *buf = &substream->dma_buffer; @@ -267,24 +269,32 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,  	return 0;  } -static struct snd_soc_platform imx_soc_platform_fiq = { -	.pcm_ops 	= &imx_pcm_ops, +static void imx_pcm_fiq_free(struct snd_pcm *pcm) +{ +	mxc_set_irq_fiq(ssi_irq, 0); +	release_fiq(&fh); +	imx_pcm_free(pcm); +} + +static struct snd_soc_platform_driver imx_soc_platform_fiq = { +	.ops		= &imx_pcm_ops,  	.pcm_new	= imx_pcm_fiq_new, -	.pcm_free	= imx_pcm_free, +	.pcm_free	= imx_pcm_fiq_free,  }; -struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, -		struct imx_ssi *ssi) +static int __devinit imx_soc_platform_probe(struct platform_device *pdev)  { -	int ret = 0; +	struct imx_ssi *ssi = platform_get_drvdata(pdev); +	int ret;  	ret = claim_fiq(&fh);  	if (ret) {  		dev_err(&pdev->dev, "failed to claim fiq: %d", ret); -		return ERR_PTR(ret); +		return ret;  	}  	mxc_set_irq_fiq(ssi->irq, 1); +	ssi_irq = ssi->irq;  	imx_pcm_fiq = ssi->irq; @@ -293,13 +303,43 @@ struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,  	ssi->dma_params_tx.burstsize = 4;  	ssi->dma_params_rx.burstsize = 6; -	return &imx_soc_platform_fiq; +	ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); +	if (ret) +		goto failed_register; + +	return 0; + +failed_register: +	mxc_set_irq_fiq(ssi_irq, 0); +	release_fiq(&fh); + +	return ret;  } -void imx_ssi_fiq_exit(struct platform_device *pdev, -		struct imx_ssi *ssi) +static int __devexit imx_soc_platform_remove(struct platform_device *pdev)  { -	mxc_set_irq_fiq(ssi->irq, 0); -	release_fiq(&fh); +	snd_soc_unregister_platform(&pdev->dev); +	return 0;  } +static struct platform_driver imx_pcm_driver = { +	.driver = { +			.name = "imx-fiq-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = imx_soc_platform_probe, +	.remove = __devexit_p(imx_soc_platform_remove), +}; + +static int __init snd_imx_pcm_init(void) +{ +	return platform_driver_register(&imx_pcm_driver); +} +module_init(snd_imx_pcm_init); + +static void __exit snd_imx_pcm_exit(void) +{ +	platform_driver_unregister(&imx_pcm_driver); +} +module_exit(snd_imx_pcm_exit); diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 50f51624c535..02a3e7c799d8 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -61,7 +61,7 @@  static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,  	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)  { -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);  	u32 sccr;  	sccr = readl(ssi->base + SSI_STCCR); @@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,   */  static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)  { -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);  	u32 strcr = 0, scr;  	scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); @@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)  static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,  				  int clk_id, unsigned int freq, int dir)  { -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);  	u32 scr;  	scr = readl(ssi->base + SSI_SCR); @@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,  static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,  				  int div_id, int div)  { -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);  	u32 stccr, srccr;  	stccr = readl(ssi->base + SSI_STCCR); @@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,  			     struct snd_pcm_hw_params *params,  			     struct snd_soc_dai *cpu_dai)  { -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);  	struct imx_pcm_dma_params *dma_data;  	u32 reg, sccr; @@ -279,9 +279,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,  static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,  		struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct imx_ssi *ssi = cpu_dai->private_data; +	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);  	unsigned int sier_bits, sier;  	unsigned int scr; @@ -350,22 +348,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {  	.trigger	= imx_ssi_trigger,  }; -static struct snd_soc_dai imx_ssi_dai = { -	.playback = { -		.channels_min = 2, -		.channels_max = 2, -		.rates = SNDRV_PCM_RATE_8000_96000, -		.formats = SNDRV_PCM_FMTBIT_S16_LE, -	}, -	.capture = { -		.channels_min = 2, -		.channels_max = 2, -		.rates = SNDRV_PCM_RATE_8000_96000, -		.formats = SNDRV_PCM_FMTBIT_S16_LE, -	}, -	.ops = &imx_ssi_pcm_dai_ops, -}; -  int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,  		struct vm_area_struct *vma)  { @@ -381,6 +363,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,  			runtime->dma_bytes);  	return ret;  } +EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);  static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)  { @@ -412,14 +395,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  		card->dev->dma_mask = &imx_pcm_dmamask;  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = imx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = imx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -429,6 +412,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  out:  	return ret;  } +EXPORT_SYMBOL_GPL(imx_pcm_new);  void imx_pcm_free(struct snd_pcm *pcm)  { @@ -450,14 +434,40 @@ void imx_pcm_free(struct snd_pcm *pcm)  		buf->area = NULL;  	}  } +EXPORT_SYMBOL_GPL(imx_pcm_free); -struct snd_soc_platform imx_soc_platform = { -	.name		= "imx-audio", +static struct snd_soc_dai_driver imx_ssi_dai = { +	.playback = { +		.channels_min = 2, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000_96000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE, +	}, +	.capture = { +		.channels_min = 2, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000_96000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE, +	}, +	.ops = &imx_ssi_pcm_dai_ops,  }; -EXPORT_SYMBOL_GPL(imx_soc_platform); -static struct snd_soc_dai imx_ac97_dai = { -	.name = "AC97", +static int imx_ssi_dai_probe(struct snd_soc_dai *dai) +{ +	struct imx_ssi *ssi = dev_get_drvdata(dai->dev); +	uint32_t val; + +	snd_soc_dai_set_drvdata(dai, ssi); + +	val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | +		SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); +	writel(val, ssi->base + SSI_SFCSR); + +	return 0; +} + +static struct snd_soc_dai_driver imx_ac97_dai = { +	.probe = imx_ssi_dai_probe,  	.ac97_control = 1,  	.playback = {  		.stream_name = "AC97 Playback", @@ -577,25 +587,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = {  };  EXPORT_SYMBOL_GPL(soc_ac97_ops); -struct snd_soc_dai imx_ssi_pcm_dai[2]; -EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai); -  static int imx_ssi_probe(struct platform_device *pdev)  {  	struct resource *res;  	struct imx_ssi *ssi;  	struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; -	struct snd_soc_platform *platform;  	int ret = 0; -	unsigned int val; -	struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; - -	if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai)) -		return -EINVAL; +	struct snd_soc_dai_driver *dai;  	ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);  	if (!ssi)  		return -ENOMEM; +	dev_set_drvdata(&pdev->dev, ssi);  	if (pdata) {  		ssi->ac97_reset = pdata->ac97_reset; @@ -640,9 +643,9 @@ static int imx_ssi_probe(struct platform_device *pdev)  		}  		ac97_ssi = ssi;  		setup_channel_to_ac97(ssi); -		memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); +		dai = &imx_ac97_dai;  	} else -		memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); +		dai = &imx_ssi_dai;  	writel(0x0, ssi->base + SSI_SIER); @@ -657,37 +660,36 @@ static int imx_ssi_probe(struct platform_device *pdev)  	if (res)  		ssi->dma_params_rx.dma = res->start; -	dai->id = pdev->id; -	dai->dev = &pdev->dev; -	dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id); -	dai->private_data = ssi; -  	if ((cpu_is_mx27() || cpu_is_mx21()) &&  			!(ssi->flags & IMX_SSI_USE_AC97) &&  			(ssi->flags & IMX_SSI_DMA)) {  		ssi->flags |= IMX_SSI_DMA; -		platform = imx_ssi_dma_mx2_init(pdev, ssi); -	} else -		platform = imx_ssi_fiq_init(pdev, ssi); - -	imx_soc_platform.pcm_ops = platform->pcm_ops; -	imx_soc_platform.pcm_new = platform->pcm_new; -	imx_soc_platform.pcm_free = platform->pcm_free; +	} -	val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | -		SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); -	writel(val, ssi->base + SSI_SFCSR); +	platform_set_drvdata(pdev, ssi); -	ret = snd_soc_register_dai(dai); +	ret = snd_soc_register_dai(&pdev->dev, dai);  	if (ret) {  		dev_err(&pdev->dev, "register DAI failed\n");  		goto failed_register;  	} -	platform_set_drvdata(pdev, ssi); +	ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); +	if (!ssi->soc_platform_pdev) +		goto failed_pdev_alloc; +	platform_set_drvdata(ssi->soc_platform_pdev, ssi); +	ret = platform_device_add(ssi->soc_platform_pdev); +	if (ret) { +		dev_err(&pdev->dev, "failed to add platform device\n"); +		goto failed_pdev_add; +	}  	return 0; +failed_pdev_add: +	platform_device_put(ssi->soc_platform_pdev); +failed_pdev_alloc: +	snd_soc_unregister_dai(&pdev->dev);  failed_register:  failed_ac97:  	iounmap(ssi->base); @@ -706,16 +708,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)  {  	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	struct imx_ssi *ssi = platform_get_drvdata(pdev); -	struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; -	snd_soc_unregister_dai(dai); +	platform_device_del(ssi->soc_platform_pdev); +	platform_device_put(ssi->soc_platform_pdev); + +	snd_soc_unregister_dai(&pdev->dev);  	if (ssi->flags & IMX_SSI_USE_AC97)  		ac97_ssi = NULL; -	if (!(ssi->flags & IMX_SSI_DMA)) -		imx_ssi_fiq_exit(pdev, ssi); -  	iounmap(ssi->base);  	release_mem_region(res->start, resource_size(res));  	clk_disable(ssi->clk); @@ -730,34 +731,19 @@ static struct platform_driver imx_ssi_driver = {  	.remove = __devexit_p(imx_ssi_remove),  	.driver = { -		.name = DRV_NAME, +		.name = "imx-ssi-dai",  		.owner = THIS_MODULE,  	},  };  static int __init imx_ssi_init(void)  { -	int ret; - -	ret = snd_soc_register_platform(&imx_soc_platform); -	if (ret) { -		pr_err("failed to register soc platform: %d\n", ret); -		return ret; -	} - -	ret = platform_driver_register(&imx_ssi_driver); -	if (ret) { -		snd_soc_unregister_platform(&imx_soc_platform); -		return ret; -	} - -	return 0; +	return platform_driver_register(&imx_ssi_driver);  }  static void __exit imx_ssi_exit(void)  {  	platform_driver_unregister(&imx_ssi_driver); -	snd_soc_unregister_platform(&imx_soc_platform);  }  module_init(imx_ssi_init); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 55f26ebcd8c2..53b780d9b2b0 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -183,9 +183,6 @@  #define IMX_SSI_RX_DIV_PSR	4  #define IMX_SSI_RX_DIV_PM	5 -extern struct snd_soc_dai imx_ssi_pcm_dai[2]; -extern struct snd_soc_platform imx_soc_platform; -  #define DRV_NAME "imx-ssi"  struct imx_pcm_dma_params { @@ -197,7 +194,7 @@ struct imx_pcm_dma_params {  struct imx_ssi {  	struct platform_device *ac97_dev; -	struct snd_soc_device imx_ac97; +	struct snd_soc_dai *imx_ac97;  	struct clk *clk;  	void __iomem *base;  	int irq; @@ -213,6 +210,8 @@ struct imx_ssi {  	struct imx_pcm_dma_params	dma_params_tx;  	int enabled; + +	struct platform_device *soc_platform_pdev;  };  struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index a8307d55c70e..65f0f99ca6dd 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -32,23 +32,20 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {  	{  		.name		= "HiFi",  		.stream_name	= "HiFi", -		.codec_dai	= &wm9712_dai[WM9712_DAI_AC97_HIFI], +		.codec_dai_name		= "wm9712-hifi", +		.codec_name	= "wm9712-codec", +		.cpu_dai_name	= "imx-ssi-dai.0", +		.platform_name	= "imx-fiq-pcm-audio.0",  		.ops		= &imx_phycore_hifi_ops,  	},  };  static struct snd_soc_card imx_phycore = {  	.name		= "PhyCORE-audio", -	.platform	= &imx_soc_platform,  	.dai_link	= imx_phycore_dai_ac97,  	.num_links	= ARRAY_SIZE(imx_phycore_dai_ac97),  }; -static struct snd_soc_device imx_phycore_snd_devdata = { -	.card		= &imx_phycore, -	.codec_dev	= &soc_codec_dev_wm9712, -}; -  static struct platform_device *imx_phycore_snd_device;  static int __init imx_phycore_init(void) @@ -63,10 +60,12 @@ static int __init imx_phycore_init(void)  	if (!imx_phycore_snd_device)  		return -ENOMEM; -	imx_phycore_dai_ac97[0].cpu_dai = &imx_ssi_pcm_dai[0]; +	platform_set_drvdata(imx_phycore_snd_device, &imx_phycore); +	ret = platform_device_add(imx_phycore_snd_device); -	platform_set_drvdata(imx_phycore_snd_device, &imx_phycore_snd_devdata); -	imx_phycore_snd_devdata.dev = &imx_phycore_snd_device->dev; +	imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); +	if (!imx_phycore_snd_device) +		return -ENOMEM;  	ret = platform_device_add(imx_phycore_snd_device);  	if (ret) { diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index a6e7d9497639..74068636c1d8 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c @@ -82,8 +82,8 @@ static int wm1133_ev1_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int i, found = 0;  	snd_pcm_format_t format = params_format(params);  	unsigned int rate = params_rate(params); @@ -210,9 +210,9 @@ static struct snd_soc_jack_pin mic_jack_pins[] = {  	{ .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE },  }; -static int wm1133_ev1_init(struct snd_soc_codec *codec) +static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)  { -	struct snd_soc_card *card = codec->socdev->card; +	struct snd_soc_codec *codec = rtd->codec;  	snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets,  				  ARRAY_SIZE(wm1133_ev1_widgets)); @@ -221,13 +221,13 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)  				ARRAY_SIZE(wm1133_ev1_map));  	/* Headphone jack detection */ -	snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack); +	snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack);  	snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),  			      hp_jack_pins);  	wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);  	/* Microphone jack detection */ -	snd_soc_jack_new(card, "Microphone", +	snd_soc_jack_new(codec, "Microphone",  			 SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);  	snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),  			      mic_jack_pins); @@ -243,8 +243,10 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link wm1133_ev1_dai = {  	.name = "WM1133-EV1",  	.stream_name = "Audio", -	.cpu_dai = &imx_ssi_pcm_dai[0], -	.codec_dai = &wm8350_dai, +	.cpu_dai_name = "imx-ssi-dai.0", +	.codec_dai_name = "wm8350-hifi", +	.platform_name = "imx-fiq-pcm-audio.0", +	.codec_name = "wm8350-codec.0-0x1a",  	.init = wm1133_ev1_init,  	.ops = &wm1133_ev1_ops,  	.symmetric_rates = 1, @@ -252,16 +254,10 @@ static struct snd_soc_dai_link wm1133_ev1_dai = {  static struct snd_soc_card wm1133_ev1 = {  	.name = "WM1133-EV1", -	.platform = &imx_soc_platform,  	.dai_link = &wm1133_ev1_dai,  	.num_links = 1,  }; -static struct snd_soc_device wm1133_ev1_snd_devdata = { -	.card = &wm1133_ev1, -	.codec_dev = &soc_codec_dev_wm8350, -}; -  static struct platform_device *wm1133_ev1_snd_device;  static int __init wm1133_ev1_audio_init(void) @@ -286,8 +282,7 @@ static int __init wm1133_ev1_audio_init(void)  	if (!wm1133_ev1_snd_device)  		return -ENOMEM; -	platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata); -	wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev; +	platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1);  	ret = platform_device_add(wm1133_ev1_snd_device);  	if (ret) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index eb518f0c5e01..f3cffd183401 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -106,15 +106,10 @@ static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,  	writel(value, i2s->base + reg);  } -static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai) -{ -	return dai->private_data; -} -  static int jz4740_i2s_startup(struct snd_pcm_substream *substream,  	struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t conf, ctrl;  	if (dai->active) @@ -136,7 +131,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream,  static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,  	struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t conf;  	if (!dai->active) @@ -152,7 +147,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,  static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  	struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t ctrl;  	uint32_t mask; @@ -186,7 +181,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t format = 0;  	uint32_t conf; @@ -238,7 +233,7 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)  static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,  	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	enum jz4740_dma_width dma_width;  	struct jz4740_pcm_config *pcm_config;  	unsigned int sample_size; @@ -288,7 +283,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,  static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,  	unsigned int freq, int dir)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	struct clk *parent;  	int ret = 0; @@ -312,7 +307,7 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,  static int jz4740_i2s_suspend(struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t conf;  	if (dai->active) { @@ -330,7 +325,7 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai)  static int jz4740_i2s_resume(struct snd_soc_dai *dai)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t conf;  	clk_enable(i2s->clk_aic); @@ -346,11 +341,38 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)  	return 0;  } -static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) +static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)  { -	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); +	struct jz4740_dma_config *dma_config; + +	/* Playback */ +	dma_config = &i2s->pcm_config_playback.dma_config; +	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; +	dma_config->flags = JZ4740_DMA_SRC_AUTOINC; +	dma_config->mode = JZ4740_DMA_MODE_SINGLE; +	i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; + +	/* Capture */ +	dma_config = &i2s->pcm_config_capture.dma_config; +	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; +	dma_config->flags = JZ4740_DMA_DST_AUTOINC; +	dma_config->mode = JZ4740_DMA_MODE_SINGLE; +	i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; +} + +static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) +{ +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);  	uint32_t conf; +	clk_enable(i2s->clk_aic); + +	jz4740_i2c_init_pcm_config(i2s); +  	conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |  		(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |  		JZ_AIC_CONF_OVERFLOW_PLAY_LAST | @@ -363,6 +385,14 @@ static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *da  	return 0;  } +static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) +{ +	struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); + +	clk_disable(i2s->clk_aic); +	return 0; +} +  static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {  	.startup = jz4740_i2s_startup,  	.shutdown = jz4740_i2s_shutdown, @@ -375,9 +405,9 @@ static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {  #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \  		SNDRV_PCM_FMTBIT_S16_LE) -struct snd_soc_dai jz4740_i2s_dai = { -	.name = "jz4740-i2s", -	.probe = jz4740_i2s_probe, +static struct snd_soc_dai_driver jz4740_i2s_dai = { +	.probe = jz4740_i2s_dai_probe, +	.remove = jz4740_i2s_dai_remove,  	.playback = {  		.channels_min = 1,  		.channels_max = 2, @@ -395,30 +425,6 @@ struct snd_soc_dai jz4740_i2s_dai = {  	.suspend = jz4740_i2s_suspend,  	.resume = jz4740_i2s_resume,  }; -EXPORT_SYMBOL_GPL(jz4740_i2s_dai); - -static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) -{ -	struct jz4740_dma_config *dma_config; - -	/* Playback */ -	dma_config = &i2s->pcm_config_playback.dma_config; -	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, -	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; -	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; -	dma_config->flags = JZ4740_DMA_SRC_AUTOINC; -	dma_config->mode = JZ4740_DMA_MODE_SINGLE; -	i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; - -	/* Capture */ -	dma_config = &i2s->pcm_config_capture.dma_config; -	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, -	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; -	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; -	dma_config->flags = JZ4740_DMA_DST_AUTOINC; -	dma_config->mode = JZ4740_DMA_MODE_SINGLE; -	i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; -}  static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)  { @@ -463,24 +469,17 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)  		goto err_clk_put_aic;  	} -	clk_enable(i2s->clk_aic); - -	jz4740_i2c_init_pcm_config(i2s); - -	jz4740_i2s_dai.private_data = i2s; -	ret = snd_soc_register_dai(&jz4740_i2s_dai); +	platform_set_drvdata(pdev, i2s); +	ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai);  	if (ret) {  		dev_err(&pdev->dev, "Failed to register DAI\n");  		goto err_clk_put_i2s;  	} -	platform_set_drvdata(pdev, i2s); -  	return 0;  err_clk_put_i2s: -	clk_disable(i2s->clk_aic);  	clk_put(i2s->clk_i2s);  err_clk_put_aic:  	clk_put(i2s->clk_aic); @@ -498,9 +497,8 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)  {  	struct jz4740_i2s *i2s = platform_get_drvdata(pdev); -	snd_soc_unregister_dai(&jz4740_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev); -	clk_disable(i2s->clk_aic);  	clk_put(i2s->clk_i2s);  	clk_put(i2s->clk_aic); diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h index da22ed88a589..5e49339d8b93 100644 --- a/sound/soc/jz4740/jz4740-i2s.h +++ b/sound/soc/jz4740/jz4740-i2s.h @@ -13,6 +13,4 @@  #define JZ4740_I2S_BIT_CLK		0 -extern struct snd_soc_dai jz4740_i2s_dai; -  #endif diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c index ee68d850c8dd..fb1483f7c966 100644 --- a/sound/soc/jz4740/jz4740-pcm.c +++ b/sound/soc/jz4740/jz4740-pcm.c @@ -109,7 +109,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct jz4740_pcm_config *config; -	config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	if (!config)  		return 0; @@ -310,14 +310,14 @@ int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = jz4740_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto err;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = jz4740_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -328,22 +328,20 @@ err:  	return ret;  } -struct snd_soc_platform jz4740_soc_platform = { -		.name		= "jz4740-pcm", -		.pcm_ops	= &jz4740_pcm_ops, +static struct snd_soc_platform_driver jz4740_soc_platform = { +		.ops		= &jz4740_pcm_ops,  		.pcm_new	= jz4740_pcm_new,  		.pcm_free	= jz4740_pcm_free,  }; -EXPORT_SYMBOL_GPL(jz4740_soc_platform);  static int __devinit jz4740_pcm_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&jz4740_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);  }  static int __devexit jz4740_pcm_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&jz4740_soc_platform); +	snd_soc_unregister_platform(&pdev->dev);  	return 0;  } @@ -351,7 +349,7 @@ static struct platform_driver jz4740_pcm_driver = {  	.probe = jz4740_pcm_probe,  	.remove = __devexit_p(jz4740_pcm_remove),  	.driver = { -		.name = "jz4740-pcm", +		.name = "jz4740-pcm-audio",  		.owner = THIS_MODULE,  	},  }; diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h index e3f221e2779c..1220cbb4382c 100644 --- a/sound/soc/jz4740/jz4740-pcm.h +++ b/sound/soc/jz4740/jz4740-pcm.h @@ -11,8 +11,6 @@  #include <linux/dma-mapping.h>  #include <asm/mach-jz4740/dma.h> -/* platform data */ -extern struct snd_soc_platform jz4740_soc_platform;  struct jz4740_pcm_config {  	struct jz4740_dma_config dma_config; diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c index f15f4918f15f..78dabebe8fd0 100644 --- a/sound/soc/jz4740/qi_lb60.c +++ b/sound/soc/jz4740/qi_lb60.c @@ -60,10 +60,11 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = {  			SND_SOC_DAIFMT_NB_NF | \  			SND_SOC_DAIFMT_CBM_CFM) -static int qi_lb60_codec_init(struct snd_soc_codec *codec) +static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret; -	struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;  	snd_soc_dapm_nc_pin(codec, "LIN");  	snd_soc_dapm_nc_pin(codec, "RIN"); @@ -84,8 +85,10 @@ static int qi_lb60_codec_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link qi_lb60_dai = {  	.name = "jz4740",  	.stream_name = "jz4740", -	.cpu_dai = &jz4740_i2s_dai, -	.codec_dai = &jz4740_codec_dai, +	.cpu_dai_name = "jz4740-i2s", +	.platform_name = "jz4740-pmc-audio", +	.codec_dai_name = "jz4740-hifi", +	.codec_name = "jz4740-codec",  	.init = qi_lb60_codec_init,  }; @@ -93,12 +96,6 @@ static struct snd_soc_card qi_lb60 = {  	.name = "QI LB60",  	.dai_link = &qi_lb60_dai,  	.num_links = 1, -	.platform = &jz4740_soc_platform, -}; - -static struct snd_soc_device qi_lb60_snd_devdata = { -	.card = &qi_lb60, -	.codec_dev = &soc_codec_dev_jz4740_codec,  };  static struct platform_device *qi_lb60_snd_device; @@ -129,8 +126,7 @@ static int __init qi_lb60_init(void)  	gpio_direction_output(QI_LB60_SND_GPIO, 0);  	gpio_direction_output(QI_LB60_AMP_GPIO, 0); -	platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata); -	qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev; +	platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);  	ret = platform_device_add(qi_lb60_snd_device);  	if (ret) { diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index a30205be3e2b..693049d42d24 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -18,7 +18,6 @@  #include <linux/dma-mapping.h>  #include <linux/mbus.h>  #include <sound/soc.h> -#include "kirkwood-dma.h"  #include "kirkwood.h"  #define KIRKWOOD_RATES \ @@ -123,9 +122,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)  	int err;  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; -	struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; +	struct snd_soc_platform *platform = soc_runtime->platform; +	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;  	struct kirkwood_dma_data *priv; -	struct kirkwood_dma_priv *prdata = cpu_dai->private_data; +	struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);  	unsigned long addr;  	priv = snd_soc_dai_get_dma_data(cpu_dai, substream); @@ -151,7 +151,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)  	if (err < 0)  		return err; -	if (soc_runtime->dai->cpu_dai->private_data == NULL) { +	if (prdata == NULL) {  		prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);  		if (prdata == NULL)  			return -ENOMEM; @@ -165,7 +165,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)  			return -EBUSY;  		} -		soc_runtime->dai->cpu_dai->private_data = prdata; +		snd_soc_platform_set_drvdata(platform, prdata);  		/*  		 * Enable Error interrupts. We're only ack'ing them but @@ -191,8 +191,9 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)  static int kirkwood_dma_close(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; -	struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; -	struct kirkwood_dma_priv *prdata = cpu_dai->private_data; +	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; +	struct snd_soc_platform *platform = soc_runtime->platform; +	struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);  	struct kirkwood_dma_data *priv;  	priv = snd_soc_dai_get_dma_data(cpu_dai, substream); @@ -209,7 +210,7 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream)  		writel(0, priv->io + KIRKWOOD_ERR_MASK);  		free_irq(priv->irq, prdata);  		kfree(prdata); -		soc_runtime->dai->cpu_dai->private_data = NULL; +		snd_soc_platform_set_drvdata(platform, NULL);  	}  	return 0; @@ -236,7 +237,7 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; -	struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;  	struct kirkwood_dma_data *priv;  	unsigned long size, count; @@ -265,7 +266,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream  						*substream)  {  	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; -	struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;  	struct kirkwood_dma_data *priv;  	snd_pcm_uframes_t count; @@ -320,14 +321,14 @@ static int kirkwood_dma_new(struct snd_card *card,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = 0xffffffff; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = kirkwood_dma_preallocate_dma_buffer(pcm,  				SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			return ret;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = kirkwood_dma_preallocate_dma_buffer(pcm,  				SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -357,25 +358,44 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)  	}  } -struct snd_soc_platform kirkwood_soc_platform = { -	.name		= "kirkwood-dma", -	.pcm_ops	= &kirkwood_dma_ops, +static struct snd_soc_platform_driver kirkwood_soc_platform = { +	.ops		= &kirkwood_dma_ops,  	.pcm_new	= kirkwood_dma_new,  	.pcm_free	= kirkwood_dma_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(kirkwood_soc_platform); -static int __init kirkwood_soc_platform_init(void) +static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&kirkwood_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);  } -module_init(kirkwood_soc_platform_init); -static void __exit kirkwood_soc_platform_exit(void) +static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&kirkwood_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver kirkwood_pcm_driver = { +	.driver = { +			.name = "kirkwood-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = kirkwood_soc_platform_probe, +	.remove = __devexit_p(kirkwood_soc_platform_remove), +}; + +static int __init kirkwood_pcm_init(void) +{ +	return platform_driver_register(&kirkwood_pcm_driver); +} +module_init(kirkwood_pcm_init); + +static void __exit kirkwood_pcm_exit(void) +{ +	platform_driver_unregister(&kirkwood_pcm_driver);  } -module_exit(kirkwood_soc_platform_exit); +module_exit(kirkwood_pcm_exit);  MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");  MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h deleted file mode 100644 index ba4454cd34f1..000000000000 --- a/sound/soc/kirkwood/kirkwood-dma.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * kirkwood-dma.h - * - * (c) 2010 Arnaud Patard <apatard@mandriva.com> - * - *  This program is free software; you can redistribute  it and/or modify it - *  under  the terms of  the GNU General  Public License as published by the - *  Free Software Foundation;  either version 2 of the  License, or (at your - *  option) any later version. - */ - -#ifndef _KIRKWOOD_DMA_H -#define _KIRKWOOD_DMA_H - -extern struct snd_soc_platform kirkwood_soc_platform; - -#endif diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 981ffc2a13c8..9b62cba4f590 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -20,7 +20,6 @@  #include <sound/pcm_params.h>  #include <sound/soc.h>  #include <plat/audio.h> -#include "kirkwood-i2s.h"  #include "kirkwood.h"  #define DRV_NAME	"kirkwood-i2s" @@ -33,13 +32,10 @@  	 SNDRV_PCM_FMTBIT_S24_LE | \  	 SNDRV_PCM_FMTBIT_S32_LE) - -struct snd_soc_dai kirkwood_i2s_dai; -static struct kirkwood_dma_data *priv; -  static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,  		unsigned int fmt)  { +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);  	unsigned long mask;  	unsigned long value; @@ -101,10 +97,20 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)  	} while (value == 0);  } +static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, +		struct snd_soc_dai *dai) +{ +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); + +	snd_soc_dai_set_dma_data(dai, substream, priv); +	return 0; +} +  static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *dai)  { +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);  	unsigned int i2s_reg, reg;  	unsigned long i2s_value, value; @@ -171,6 +177,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,  static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,  				int cmd, struct snd_soc_dai *dai)  { +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);  	unsigned long value;  	/* @@ -244,6 +251,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,  static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,  				int cmd, struct snd_soc_dai *dai)  { +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);  	unsigned long value;  	value = readl(priv->io + KIRKWOOD_RECCTL); @@ -323,9 +331,9 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  	return 0;  } -static int kirkwood_i2s_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int kirkwood_i2s_probe(struct snd_soc_dai *dai)  { +	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);  	unsigned long value;  	unsigned int reg_data; @@ -359,21 +367,20 @@ static int kirkwood_i2s_probe(struct platform_device *pdev,  } -static void kirkwood_i2s_remove(struct platform_device *pdev, -				struct snd_soc_dai *dai) +static int kirkwood_i2s_remove(struct snd_soc_dai *dai)  { +	return 0;  }  static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { +	.startup	= kirkwood_i2s_startup,  	.trigger	= kirkwood_i2s_trigger,  	.hw_params      = kirkwood_i2s_hw_params,  	.set_fmt        = kirkwood_i2s_set_fmt,  }; -struct snd_soc_dai kirkwood_i2s_dai = { -	.name = DRV_NAME, -	.id = 0, +static struct snd_soc_dai_driver kirkwood_i2s_dai = {  	.probe = kirkwood_i2s_probe,  	.remove = kirkwood_i2s_remove,  	.playback = { @@ -388,13 +395,13 @@ struct snd_soc_dai kirkwood_i2s_dai = {  		.formats = KIRKWOOD_I2S_FORMATS,},  	.ops = &kirkwood_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(kirkwood_i2s_dai);  static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)  {  	struct resource *mem;  	struct kirkwood_asoc_platform_data *data =  		pdev->dev.platform_data; +	struct kirkwood_dma_data *priv;  	int err;  	priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); @@ -403,6 +410,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)  		err = -ENOMEM;  		goto error;  	} +	dev_set_drvdata(&pdev->dev, priv);  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!mem) { @@ -441,10 +449,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)  	priv->dram = data->dram;  	priv->burst = data->burst; -	kirkwood_i2s_dai.capture.dma_data = priv; -	kirkwood_i2s_dai.playback.dma_data = priv; - -	return snd_soc_register_dai(&kirkwood_i2s_dai); +	return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);  err_ioremap:  	iounmap(priv->io); @@ -458,12 +463,13 @@ error:  static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)  { -	if (priv) { -		iounmap(priv->io); -		release_mem_region(priv->mem->start, SZ_16K); -		kfree(priv); -	} -	snd_soc_unregister_dai(&kirkwood_i2s_dai); +	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); + +	snd_soc_unregister_dai(&pdev->dev); +	iounmap(priv->io); +	release_mem_region(priv->mem->start, SZ_16K); +	kfree(priv); +  	return 0;  } diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h deleted file mode 100644 index c5595c616d7a..000000000000 --- a/sound/soc/kirkwood/kirkwood-i2s.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * kirkwood-i2s.h - * - * (c) 2010 Arnaud Patard <apatard@mandriva.com> - * - *  This program is free software; you can redistribute  it and/or modify it - *  under  the terms of  the GNU General  Public License as published by the - *  Free Software Foundation;  either version 2 of the  License, or (at your - *  option) any later version. - */ - -#ifndef _KIRKWOOD_I2S_H -#define _KIRKWOOD_I2S_H - -extern struct snd_soc_dai kirkwood_i2s_dai; - -#endif diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c index 0353d06bc41a..cc1a1e277edf 100644 --- a/sound/soc/kirkwood/kirkwood-openrd.c +++ b/sound/soc/kirkwood/kirkwood-openrd.c @@ -18,16 +18,14 @@  #include <mach/kirkwood.h>  #include <plat/audio.h>  #include <asm/mach-types.h> -#include "kirkwood-i2s.h" -#include "kirkwood-dma.h"  #include "../codecs/cs42l51.h"  static int openrd_client_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	unsigned int freq, fmt; @@ -66,8 +64,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {  {  	.name = "CS42L51",  	.stream_name = "CS42L51 HiFi", -	.cpu_dai = &kirkwood_i2s_dai, -	.codec_dai = &cs42l51_dai, +	.cpu_dai_name = "kirkwood-i2s", +	.platform_name = "kirkwood-pcm-audio", +	.codec_dai_name = "cs42l51_hifi", +	.codec_name = "cs42l51-codec.0-004a",  	.ops = &openrd_client_ops,  },  }; @@ -75,16 +75,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {  static struct snd_soc_card openrd_client = {  	.name = "OpenRD Client", -	.platform = &kirkwood_soc_platform,  	.dai_link = openrd_client_dai,  	.num_links = ARRAY_SIZE(openrd_client_dai),  }; -static struct snd_soc_device openrd_client_snd_devdata = { -	.card = &openrd_client, -	.codec_dev = &soc_codec_device_cs42l51, -}; -  static struct platform_device *openrd_client_snd_device;  static int __init openrd_client_init(void) @@ -99,8 +93,7 @@ static int __init openrd_client_init(void)  		return -ENOMEM;  	platform_set_drvdata(openrd_client_snd_device, -			&openrd_client_snd_devdata); -	openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev; +			&openrd_client);  	ret = platform_device_add(openrd_client_snd_device);  	if (ret) { diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index caa7c901bc2e..02b64a17dec2 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c @@ -297,8 +297,7 @@ static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {  	.trigger	= nuc900_ac97_trigger,  }; -struct snd_soc_dai nuc900_ac97_dai = { -	.name			= "nuc900-ac97", +static struct snd_soc_dai_driver nuc900_ac97_dai = {  	.probe			= nuc900_ac97_probe,  	.remove			= nuc900_ac97_remove,  	.ac97_control		= 1, @@ -316,7 +315,6 @@ struct snd_soc_dai nuc900_ac97_dai = {  	},  	.ops = &nuc900_ac97_dai_ops,  } -EXPORT_SYMBOL_GPL(nuc900_ac97_dai);  static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)  { @@ -365,9 +363,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)  	nuc900_ac97_data = nuc900_audio; -	nuc900_audio->dev = nuc900_ac97_dai.dev =  &pdev->dev; - -	ret = snd_soc_register_dai(&nuc900_ac97_dai); +	ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai);  	if (ret)  		goto out3; @@ -390,7 +386,7 @@ out0:  static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&nuc900_ac97_dai); +	snd_soc_unregister_dai(&pdev->dev);  	clk_put(nuc900_ac97_data->clk);  	iounmap(nuc900_ac97_data->mmio); @@ -404,7 +400,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)  static struct platform_driver nuc900_ac97_driver = {  	.driver	= { -		.name	= "nuc900-audio", +		.name	= "nuc900-ac97",  		.owner	= THIS_MODULE,  	},  	.probe		= nuc900_ac97_drvprobe, diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c index 72e6f518f7b2..161f5b667d7b 100644 --- a/sound/soc/nuc900/nuc900-audio.c +++ b/sound/soc/nuc900/nuc900-audio.c @@ -20,26 +20,21 @@  #include <sound/soc.h>  #include <sound/soc-dapm.h> -#include "../codecs/ac97.h"  #include "nuc900-audio.h"  static struct snd_soc_dai_link nuc900evb_ac97_dai = {  	.name		= "AC97",  	.stream_name	= "AC97 HiFi", -	.cpu_dai	= &nuc900_ac97_dai, -	.codec_dai	= &ac97_dai, +	.cpu_dai_name	= "nuc900-ac97", +	.codec_dai_name	= "ac97-hifi", +	.codec_name	= "ac97-codec", +	.platform_name	= "nuc900-pcm-audio",  };  static struct snd_soc_card nuc900evb_audio_machine = {  	.name		= "NUC900EVB_AC97",  	.dai_link	= &nuc900evb_ac97_dai,  	.num_links	= 1, -	.platform	= &nuc900_soc_platform, -}; - -static struct snd_soc_device nuc900evb_ac97_devdata = { -	.card		= &nuc900evb_audio_machine, -	.codec_dev	= &soc_codec_dev_ac97,  };  static struct platform_device *nuc900evb_asoc_dev; @@ -54,9 +49,8 @@ static int __init nuc900evb_audio_init(void)  		goto out;  	/* nuc900 board audio device */ -	platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata); +	platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); -	nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev;  	ret = platform_device_add(nuc900evb_asoc_dev);  	if (ret) { diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h index 3038f519729f..aeed8ead2b2b 100644 --- a/sound/soc/nuc900/nuc900-audio.h +++ b/sound/soc/nuc900/nuc900-audio.h @@ -110,8 +110,4 @@ struct nuc900_audio {  }; -extern struct nuc900_audio *nuc900_ac97_data; -extern struct snd_soc_dai nuc900_ac97_dai; -extern struct snd_soc_platform nuc900_soc_platform; -  #endif /*end _NUC900_AUDIO_H */ diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index e81e803b3a63..195d1ac94771 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c @@ -328,26 +328,44 @@ static int nuc900_dma_new(struct snd_card *card,  	return 0;  } -struct snd_soc_platform nuc900_soc_platform = { -	.name		= "nuc900-dma", -	.pcm_ops	= &nuc900_dma_ops, +static struct snd_soc_platform_driver nuc900_soc_platform = { +	.ops		= &nuc900_dma_ops,  	.pcm_new	= nuc900_dma_new,  	.pcm_free	= nuc900_dma_free_dma_buffers,  } -EXPORT_SYMBOL_GPL(nuc900_soc_platform); -static int __init nuc900_soc_platform_init(void) +static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&nuc900_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);  } -static void __exit nuc900_soc_platform_exit(void) +static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&nuc900_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0;  } -module_init(nuc900_soc_platform_init); -module_exit(nuc900_soc_platform_exit); +static struct platform_driver nuc900_pcm_driver = { +	.driver = { +			.name = "nuc900-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = nuc900_soc_platform_probe, +	.remove = __devexit_p(nuc900_soc_platform_remove), +}; + +static int __init nuc900_pcm_init(void) +{ +	return platform_driver_register(&nuc900_pcm_driver); +} +module_init(nuc900_pcm_init); + +static void __exit nuc900_pcm_exit(void) +{ +	platform_driver_unregister(&nuc900_pcm_driver); +} +module_exit(nuc900_pcm_exit);  MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");  MODULE_DESCRIPTION("nuc900 Audio DMA module"); diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 135901b2ea11..68bd902ccd4e 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -40,8 +40,8 @@ static int am3517evm_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -111,8 +111,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MICIN", NULL, "Mic In"},  }; -static int am3517evm_aic23_init(struct snd_soc_codec *codec) +static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	/* Add am3517-evm specific widgets */  	snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,  				  ARRAY_SIZE(tlv320aic23_dapm_widgets)); @@ -134,8 +136,10 @@ static int am3517evm_aic23_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link am3517evm_dai = {  	.name = "TLV320AIC23",  	.stream_name = "AIC23", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &tlv320aic23_dai, +	.cpu_dai_name ="omap-mcbsp-dai.0", +	.codec_dai_name = "tlv320aic23-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "tlv320aic23-codec",  	.init = am3517evm_aic23_init,  	.ops = &am3517evm_ops,  }; @@ -143,17 +147,10 @@ static struct snd_soc_dai_link am3517evm_dai = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_am3517evm = {  	.name = "am3517evm", -	.platform = &omap_soc_platform,  	.dai_link = &am3517evm_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device am3517evm_snd_devdata = { -	.card = &snd_soc_am3517evm, -	.codec_dev = &soc_codec_dev_tlv320aic23, -}; -  static struct platform_device *am3517evm_snd_device;  static int __init am3517evm_soc_init(void) @@ -172,9 +169,7 @@ static int __init am3517evm_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata); -	am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev; -	*(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */ +	platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm);  	ret = platform_device_add(am3517evm_snd_device);  	if (ret) diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index b0f618e44840..9d88efa06e3c 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -99,7 +99,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,  	int pin, changed = 0;  	/* Refuse any mode changes if we are not able to control the codec. */ -	if (!codec->control_data) +	if (!codec->hw_write)  		return -EUNATCH;  	if (ucontrol->value.enumerated.item[0] >= control->max) @@ -268,10 +268,32 @@ static void cx81801_timeout(unsigned long data)  		ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);  } +/* + * Used for passing a codec structure pointer + * from the board initialization code to the tty line discipline. + */ +static struct snd_soc_codec *cx20442_codec; +  /* Line discipline .open() */  static int cx81801_open(struct tty_struct *tty)  { -	return v253_ops.open(tty); +	int ret; + +	if (!cx20442_codec) +		return -ENODEV; + +	/* +	 * Pass the codec structure pointer for use by other ldisc callbacks, +	 * both the card and the codec specific parts. +	 */ +	tty->disc_data = cx20442_codec; + +	ret = v253_ops.open(tty); + +	if (ret < 0) +		tty->disc_data = NULL; + +	return ret;  }  /* Line discipline .close() */ @@ -281,11 +303,14 @@ static void cx81801_close(struct tty_struct *tty)  	del_timer_sync(&cx81801_timer); -	v253_ops.close(tty); -  	/* Prevent the hook switch from further changing the DAPM pins */  	INIT_LIST_HEAD(&ams_delta_hook_switch.pins); +	if (!codec) +		return; + +	v253_ops.close(tty); +  	/* Revert back to default audio input/output constellation */  	snd_soc_dapm_disable_pin(codec, "Mouthpiece");  	snd_soc_dapm_enable_pin(codec, "Earpiece"); @@ -310,7 +335,10 @@ static void cx81801_receive(struct tty_struct *tty,  	const unsigned char *c;  	int apply, ret; -	if (!codec->control_data) { +	if (!codec) +		return; + +	if (!codec->hw_write) {  		/* First modem response, complete setup procedure */  		/* Initialize timer used for config pulse generation */ @@ -323,7 +351,7 @@ static void cx81801_receive(struct tty_struct *tty,  					ARRAY_SIZE(ams_delta_hook_switch_pins),  					ams_delta_hook_switch_pins);  		if (ret) -			dev_warn(codec->socdev->card->dev, +			dev_warn(codec->dev,  				"Failed to link hook switch to DAPM pins, "  				"will continue with hook switch unlinked.\n"); @@ -383,7 +411,7 @@ static int ams_delta_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	/* Set cpu DAI configuration */ -	return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, +	return snd_soc_dai_set_fmt(rtd->cpu_dai,  				   SND_SOC_DAIFMT_DSP_A |  				   SND_SOC_DAIFMT_NB_NF |  				   SND_SOC_DAIFMT_CBM_CFM); @@ -398,7 +426,7 @@ static struct snd_soc_ops ams_delta_ops = {  static int ams_delta_set_bias_level(struct snd_soc_card *card,  					enum snd_soc_bias_level level)  { -	struct snd_soc_codec *codec = card->codec; +	struct snd_soc_codec *codec = card->rtd->codec;  	switch (level) {  	case SND_SOC_BIAS_ON: @@ -461,18 +489,22 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream)   * Card initialization   */ -static int ams_delta_cx20442_init(struct snd_soc_codec *codec) +static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)  { -	struct snd_soc_dai *codec_dai = codec->dai; -	struct snd_soc_card *card = codec->socdev->card; +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_card *card = rtd->card;  	int ret;  	/* Codec is ready, now add/activate board specific controls */ +	/* Store a pointer to the codec structure for tty ldisc use */ +	cx20442_codec = codec; +  	/* Set up digital mute if not provided by the codec */ -	if (!codec_dai->ops) { -		codec_dai->ops = &ams_delta_dai_ops; -	} else if (!codec_dai->ops->digital_mute) { -		codec_dai->ops->digital_mute = ams_delta_digital_mute; +	if (!codec_dai->driver->ops) { +		codec_dai->driver->ops = &ams_delta_dai_ops; +	} else if (!codec_dai->driver->ops->digital_mute) { +		codec_dai->driver->ops->digital_mute = ams_delta_digital_mute;  	} else {  		ams_delta_ops.startup = ams_delta_startup;  		ams_delta_ops.shutdown = ams_delta_shutdown; @@ -483,7 +515,7 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)  	/* Add hook switch - can be used to control the codec from userspace  	 * even if line discipline fails */ -	ret = snd_soc_jack_new(card, "hook_switch", +	ret = snd_soc_jack_new(rtd->codec, "hook_switch",  				SND_JACK_HEADSET, &ams_delta_hook_switch);  	if (ret)  		dev_warn(card->dev, @@ -551,27 +583,22 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link ams_delta_dai_link = {  	.name = "CX20442",  	.stream_name = "CX20442", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &cx20442_dai, +	.cpu_dai_name ="omap-mcbsp-dai.0", +	.codec_dai_name = "cx20442-hifi",  	.init = ams_delta_cx20442_init, +	.platform_name = "omap-pcm-audio", +	.codec_name = "cx20442-codec",  	.ops = &ams_delta_ops,  };  /* Audio card driver */  static struct snd_soc_card ams_delta_audio_card = {  	.name = "AMS_DELTA", -	.platform = &omap_soc_platform,  	.dai_link = &ams_delta_dai_link,  	.num_links = 1,  	.set_bias_level = ams_delta_set_bias_level,  }; -/* Audio subsystem */ -static struct snd_soc_device ams_delta_snd_soc_device = { -	.card = &ams_delta_audio_card, -	.codec_dev = &cx20442_codec_dev, -}; -  /* Module init/exit */  static struct platform_device *ams_delta_audio_platform_device;  static struct platform_device *cx20442_platform_device; @@ -589,9 +616,7 @@ static int __init ams_delta_module_init(void)  		return -ENOMEM;  	platform_set_drvdata(ams_delta_audio_platform_device, -				&ams_delta_snd_soc_device); -	ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev; -	*(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1; +				&ams_delta_audio_card);  	ret = platform_device_add(ams_delta_audio_platform_device);  	if (ret) @@ -601,8 +626,8 @@ static int __init ams_delta_module_init(void)  	 * Codec platform device could be registered from elsewhere (board?),  	 * but I do it here as it makes sense only if used with the card.  	 */ -	cx20442_platform_device = platform_device_register_simple("cx20442", -								-1, NULL, 0); +	cx20442_platform_device = +		platform_device_register_simple("cx20442-codec", -1, NULL, 0);  	return 0;  err:  	platform_device_put(ams_delta_audio_platform_device); @@ -612,19 +637,6 @@ module_init(ams_delta_module_init);  static void __exit ams_delta_module_exit(void)  { -	struct snd_soc_codec *codec; -	struct tty_struct *tty; - -	if (ams_delta_audio_card.codec) { -		codec = ams_delta_audio_card.codec; - -		if (codec->control_data) { -			tty = codec->control_data; - -			tty_hangup(tty); -		} -	} -  	if (tty_unregister_ldisc(N_V253) != 0)  		dev_warn(&ams_delta_audio_platform_device->dev,  			"failed to unregister V253 line discipline\n"); diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c index 3583c429f9be..d296cfcc672e 100644 --- a/sound/soc/omap/igep0020.c +++ b/sound/soc/omap/igep0020.c @@ -33,14 +33,13 @@  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  static int igep2_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -82,25 +81,20 @@ static struct snd_soc_ops igep2_ops = {  static struct snd_soc_dai_link igep2_dai = {  	.name = "TWL4030",  	.stream_name = "TWL4030", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.codec_dai_name = "twl4030-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "twl4030-codec",  	.ops = &igep2_ops,  };  /* Audio machine driver */  static struct snd_soc_card snd_soc_card_igep2 = {  	.name = "igep2", -	.platform = &omap_soc_platform,  	.dai_link = &igep2_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device igep2_snd_devdata = { -	.card = &snd_soc_card_igep2, -	.codec_dev = &soc_codec_dev_twl4030, -}; -  static struct platform_device *igep2_snd_device;  static int __init igep2_soc_init(void) @@ -119,9 +113,7 @@ static int __init igep2_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata); -	igep2_snd_devdata.dev = &igep2_snd_device->dev; -	*(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);  	ret = platform_device_add(igep2_snd_device);  	if (ret) diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c index 90b8bf71c893..928f03707451 100644 --- a/sound/soc/omap/mcpdm.c +++ b/sound/soc/omap/mcpdm.c @@ -402,7 +402,7 @@ int omap_mcpdm_set_offset(int offset1, int offset2)  	return 0;  } -static int __devinit omap_mcpdm_probe(struct platform_device *pdev) +int __devinit omap_mcpdm_probe(struct platform_device *pdev)  {  	struct resource *res;  	int ret = 0; @@ -449,7 +449,7 @@ exit:  	return ret;  } -static int __devexit omap_mcpdm_remove(struct platform_device *pdev) +int __devexit omap_mcpdm_remove(struct platform_device *pdev)  {  	struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); @@ -468,18 +468,3 @@ static int __devexit omap_mcpdm_remove(struct platform_device *pdev)  	return 0;  } -static struct platform_driver omap_mcpdm_driver = { -	.probe = omap_mcpdm_probe, -	.remove = __devexit_p(omap_mcpdm_remove), -	.driver = { -		.name = "omap-mcpdm", -	}, -}; - -static struct platform_device *omap_mcpdm_device; - -static int __init omap_mcpdm_init(void) -{ -	return platform_driver_register(&omap_mcpdm_driver); -} -arch_initcall(omap_mcpdm_init); diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h index 7bb326ef0886..df3e16fb51f3 100644 --- a/sound/soc/omap/mcpdm.h +++ b/sound/soc/omap/mcpdm.h @@ -149,3 +149,5 @@ extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);  extern int omap_mcpdm_request(void);  extern void omap_mcpdm_free(void);  extern int omap_mcpdm_set_offset(int offset1, int offset2); +int __devinit omap_mcpdm_probe(struct platform_device *pdev); +int __devexit omap_mcpdm_remove(struct platform_device *pdev); diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 08e09d72790f..a3b6d897ad84 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -97,7 +97,7 @@ static int n810_startup(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	snd_pcm_hw_constraint_minmax(runtime,  				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); @@ -115,8 +115,8 @@ static int n810_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int err;  	/* Set codec DAI configuration */ @@ -271,8 +271,9 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {  		     n810_get_input, n810_set_input),  }; -static int n810_aic33_init(struct snd_soc_codec *codec) +static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* Not connected */ @@ -307,8 +308,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link n810_dai = {  	.name = "TLV320AIC33",  	.stream_name = "AIC33", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &aic3x_dai, +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.platform_name = "omap-pcm-audio", +	.codec_name = "tlv320aic3x-codec.2-0018", +	.codec_dai_name = "tlv320aic3x-hifi",  	.init = n810_aic33_init,  	.ops = &n810_ops,  }; @@ -316,33 +319,12 @@ static struct snd_soc_dai_link n810_dai = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_n810 = {  	.name = "N810", -	.platform = &omap_soc_platform,  	.dai_link = &n810_dai,  	.num_links = 1,  }; -/* Audio private data */ -static struct aic3x_setup_data n810_aic33_setup = { -	.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, -	.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, -}; - -/* Audio subsystem */ -static struct snd_soc_device n810_snd_devdata = { -	.card = &snd_soc_n810, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &n810_aic33_setup, -}; -  static struct platform_device *n810_snd_device; -/* temporary i2c device creation until this can be moved into the machine - * support file. -*/ -static struct i2c_board_info i2c_device[] = { -	{ I2C_BOARD_INFO("tlv320aic3x", 0x1b), } -}; -  static int __init n810_soc_init(void)  {  	int err; @@ -351,15 +333,11 @@ static int __init n810_soc_init(void)  	if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))  		return -ENODEV; -	i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device)); -  	n810_snd_device = platform_device_alloc("soc-audio", -1);  	if (!n810_snd_device)  		return -ENOMEM; -	platform_set_drvdata(n810_snd_device, &n810_snd_devdata); -	n810_snd_devdata.dev = &n810_snd_device->dev; -	*(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(n810_snd_device, &snd_soc_n810);  	err = platform_device_add(n810_snd_device);  	if (err)  		goto err1; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 86f213905e2c..7ba5690118f8 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -62,8 +62,6 @@ struct omap_mcbsp_data {  	int				wlen;  }; -#define to_mcbsp(priv)	container_of((priv), struct omap_mcbsp_data, bus_id) -  static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];  /* @@ -153,13 +151,13 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {};  static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	struct omap_pcm_dma_data *dma_data;  	int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);  	int words; -	dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */  	if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) @@ -203,11 +201,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,  }  static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, -				  struct snd_soc_dai *dai) +				  struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	int bus_id = mcbsp_data->bus_id;  	int err = 0; @@ -249,11 +245,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,  }  static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, -				    struct snd_soc_dai *dai) +				    struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	if (!cpu_dai->active) {  		omap_mcbsp_free(mcbsp_data->bus_id); @@ -262,11 +256,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,  }  static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, -				  struct snd_soc_dai *dai) +				  struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);  	switch (cmd) { @@ -295,8 +287,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(  			struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	u16 fifo_use;  	snd_pcm_sframes_t delay; @@ -317,11 +309,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(  static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,  				    struct snd_pcm_hw_params *params, -				    struct snd_soc_dai *dai) +				    struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;  	struct omap_pcm_dma_data *dma_data;  	int dma, bus_id = mcbsp_data->bus_id; @@ -496,7 +486,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,  static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,  				      unsigned int fmt)  { -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;  	unsigned int temp_fmt = fmt; @@ -596,7 +586,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,  static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,  				     int div_id, int div)  { -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;  	if (div_id != OMAP_MCBSP_CLKGDV) @@ -699,7 +689,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,  					 int clk_id, unsigned int freq,  					 int dir)  { -	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); +	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);  	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;  	int err = 0; @@ -733,7 +723,7 @@ 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 = { +static struct snd_soc_dai_ops mcbsp_dai_ops = {  	.startup	= omap_mcbsp_dai_startup,  	.shutdown	= omap_mcbsp_dai_shutdown,  	.trigger	= omap_mcbsp_dai_trigger, @@ -744,42 +734,31 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {  	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,  }; -#define OMAP_MCBSP_DAI_BUILDER(link_id)				\ -{								\ -	.name = "omap-mcbsp-dai-"#link_id,			\ -	.id = (link_id),					\ -	.playback = {						\ -		.channels_min = 1,				\ -		.channels_max = 16,				\ -		.rates = OMAP_MCBSP_RATES,			\ -		.formats = SNDRV_PCM_FMTBIT_S16_LE |		\ -			   SNDRV_PCM_FMTBIT_S32_LE,		\ -	},							\ -	.capture = {						\ -		.channels_min = 1,				\ -		.channels_max = 16,				\ -		.rates = OMAP_MCBSP_RATES,			\ -		.formats = SNDRV_PCM_FMTBIT_S16_LE |		\ -			   SNDRV_PCM_FMTBIT_S32_LE,		\ -	},							\ -	.ops = &omap_mcbsp_dai_ops,				\ -	.private_data = &mcbsp_data[(link_id)].bus_id,		\ +static int mcbsp_dai_probe(struct snd_soc_dai *dai) +{ +	mcbsp_data[dai->id].bus_id = dai->id; +	snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id); +	return 0;  } -struct snd_soc_dai omap_mcbsp_dai[] = { -	OMAP_MCBSP_DAI_BUILDER(0), -	OMAP_MCBSP_DAI_BUILDER(1), -#if NUM_LINKS >= 3 -	OMAP_MCBSP_DAI_BUILDER(2), -#endif -#if NUM_LINKS == 5 -	OMAP_MCBSP_DAI_BUILDER(3), -	OMAP_MCBSP_DAI_BUILDER(4), -#endif +static struct snd_soc_dai_driver omap_mcbsp_dai = +{ +	.probe = mcbsp_dai_probe, +	.playback = { +		.channels_min = 1, +		.channels_max = 16, +		.rates = OMAP_MCBSP_RATES, +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, +	}, +	.capture = { +		.channels_min = 1, +		.channels_max = 16, +		.rates = OMAP_MCBSP_RATES, +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, +	}, +	.ops = &mcbsp_dai_ops,  }; -EXPORT_SYMBOL_GPL(omap_mcbsp_dai); -  int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,  			struct snd_ctl_elem_info *uinfo)  { @@ -910,16 +889,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)  }  EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); +static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); +} + +static int __devexit asoc_mcbsp_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver asoc_mcbsp_driver = { +	.driver = { +			.name = "omap-mcbsp-dai", +			.owner = THIS_MODULE, +	}, + +	.probe = asoc_mcbsp_probe, +	.remove = __devexit_p(asoc_mcbsp_remove), +}; +  static int __init snd_omap_mcbsp_init(void)  { -	return snd_soc_register_dais(omap_mcbsp_dai, -				     ARRAY_SIZE(omap_mcbsp_dai)); +	return platform_driver_register(&asoc_mcbsp_driver);  }  module_init(snd_omap_mcbsp_init);  static void __exit snd_omap_mcbsp_exit(void)  { -	snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); +	platform_driver_unregister(&asoc_mcbsp_driver);  }  module_exit(snd_omap_mcbsp_exit); diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 6c363e5f4387..ffdcc5abb7b9 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -55,8 +55,6 @@ enum omap_mcbsp_div {  #define NUM_LINKS	5  #endif -extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; -  int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);  #endif diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index b7f4f7e015f3..f161c2f5ed36 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -36,7 +36,6 @@  #include <plat/dma.h>  #include <plat/mcbsp.h>  #include "mcpdm.h" -#include "omap-mcpdm.h"  #include "omap-pcm.h"  struct omap_mcpdm_data { @@ -89,11 +88,9 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {  static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,  				  struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;  	int err = 0; -	if (!cpu_dai->active) +	if (!dai->active)  		err = omap_mcpdm_request();  	return err; @@ -102,19 +99,14 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,  static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,  				    struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - -	if (!cpu_dai->active) +	if (!dai->active)  		omap_mcpdm_free();  }  static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,  				  struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; +	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);  	int stream = substream->stream;  	int err = 0; @@ -143,14 +135,12 @@ static int omap_mcpdm_dai_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_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; +	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);  	struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;  	int stream = substream->stream;  	int channels, err, link_mask = 0; -	snd_soc_dai_set_dma_data(cpu_dai, substream, +	snd_soc_dai_set_dma_data(dai, substream,  				 &omap_mcpdm_dai_dma_params[stream]);  	channels = params_channels(params); @@ -189,9 +179,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,  static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,  				  struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; +	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);  	struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;  	int stream = substream->stream;  	int err; @@ -215,9 +203,14 @@ static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {  #define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)  #define OMAP_MCPDM_FORMATS	(SNDRV_PCM_FMTBIT_S32_LE) -struct snd_soc_dai omap_mcpdm_dai = { -	.name = "omap-mcpdm", -	.id = -1, +static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai) +{ +	snd_soc_dai_set_drvdata(dai, &mcpdm_data); +	return 0; +} + +static struct snd_soc_dai_driver omap_mcpdm_dai = { +	.probe = omap_mcpdm_dai_probe,  	.playback = {  		.channels_min = 1,  		.channels_max = 4, @@ -231,19 +224,47 @@ struct snd_soc_dai omap_mcpdm_dai = {  		.formats = OMAP_MCPDM_FORMATS,  	},  	.ops = &omap_mcpdm_dai_ops, -	.private_data = &mcpdm_data,  }; -EXPORT_SYMBOL_GPL(omap_mcpdm_dai); + +static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) +{ +	int ret; + +	ret = omap_mcpdm_probe(pdev); +	if (ret < 0) +		return ret; +	ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); +	if (ret < 0) +		omap_mcpdm_remove(pdev); +	return ret; +} + +static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	omap_mcpdm_remove(pdev); +	return 0; +} + +static struct platform_driver asoc_mcpdm_driver = { +	.driver = { +			.name = "omap-mcpdm-dai", +			.owner = THIS_MODULE, +	}, + +	.probe = asoc_mcpdm_probe, +	.remove = __devexit_p(asoc_mcpdm_remove), +};  static int __init snd_omap_mcpdm_init(void)  { -	return snd_soc_register_dai(&omap_mcpdm_dai); +	return platform_driver_register(&asoc_mcpdm_driver);  }  module_init(snd_omap_mcpdm_init);  static void __exit snd_omap_mcpdm_exit(void)  { -	snd_soc_unregister_dai(&omap_mcpdm_dai); +	platform_driver_unregister(&asoc_mcpdm_driver);  }  module_exit(snd_omap_mcpdm_exit); diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h deleted file mode 100644 index 73b80d559345..000000000000 --- a/sound/soc/omap/omap-mcpdm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * omap-mcpdm.h - * - * Copyright (C) 2009 Texas Instruments - * - * Contact: Misael Lopez Cruz <x0052729@ti.com> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_MCPDM_H__ -#define __OMAP_MCPDM_H__ - -extern struct snd_soc_dai omap_mcpdm_dai; - -#endif	/* End of __OMAP_MCPDM_H__ */ diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 1e521904ea64..8caeb8d305c3 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -101,9 +101,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct omap_runtime_data *prtd = runtime->private_data;  	struct omap_pcm_dma_data *dma_data; +  	int err = 0; -	dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	/* return if this is a bufferless transfer e.g.  	 * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -374,14 +375,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(64); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = omap_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = omap_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -392,25 +393,45 @@ out:  	return ret;  } -struct snd_soc_platform omap_soc_platform = { -	.name		= "omap-pcm-audio", -	.pcm_ops 	= &omap_pcm_ops, +static struct snd_soc_platform_driver omap_soc_platform = { +	.ops		= &omap_pcm_ops,  	.pcm_new	= omap_pcm_new,  	.pcm_free	= omap_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(omap_soc_platform); -static int __init omap_soc_platform_init(void) +static __devinit int omap_pcm_probe(struct platform_device *pdev) +{ +	return snd_soc_register_platform(&pdev->dev, +			&omap_soc_platform); +} + +static int __devexit omap_pcm_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver omap_pcm_driver = { +	.driver = { +			.name = "omap-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = omap_pcm_probe, +	.remove = __devexit_p(omap_pcm_remove), +}; + +static int __init snd_omap_pcm_init(void)  { -	return snd_soc_register_platform(&omap_soc_platform); +	return platform_driver_register(&omap_pcm_driver);  } -module_init(omap_soc_platform_init); +module_init(snd_omap_pcm_init); -static void __exit omap_soc_platform_exit(void) +static void __exit snd_omap_pcm_exit(void)  { -	snd_soc_unregister_platform(&omap_soc_platform); +	platform_driver_unregister(&omap_pcm_driver);  } -module_exit(omap_soc_platform_exit); +module_exit(snd_omap_pcm_exit);  MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");  MODULE_DESCRIPTION("OMAP PCM DMA module"); diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b19975d26907..fea0515331fb 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h @@ -35,6 +35,4 @@ struct omap_pcm_dma_data {  	int		packet_size;	/* packet size only in PACKET mode */  }; -extern struct snd_soc_platform omap_soc_platform; -  #endif diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c index c7adea38274c..38cd1894623e 100644 --- a/sound/soc/omap/omap2evm.c +++ b/sound/soc/omap/omap2evm.c @@ -35,15 +35,13 @@  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  static int omap2evm_hw_params(struct snd_pcm_substream *substream, -	struct snd_pcm_hw_params *params, -	struct snd_soc_dai *dai) +	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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -85,25 +83,20 @@ static struct snd_soc_ops omap2evm_ops = {  static struct snd_soc_dai_link omap2evm_dai = {  	.name = "TWL4030",  	.stream_name = "TWL4030", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.codec_dai_name = "twl4030-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "twl4030-codec",  	.ops = &omap2evm_ops,  };  /* Audio machine driver */  static struct snd_soc_card snd_soc_omap2evm = {  	.name = "omap2evm", -	.platform = &omap_soc_platform,  	.dai_link = &omap2evm_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device omap2evm_snd_devdata = { -	.card = &snd_soc_omap2evm, -	.codec_dev = &soc_codec_dev_twl4030, -}; -  static struct platform_device *omap2evm_snd_device;  static int __init omap2evm_soc_init(void) @@ -122,9 +115,7 @@ static int __init omap2evm_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); -	omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev; -	*(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm);  	ret = platform_device_add(omap2evm_snd_device);  	if (ret) diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c index 240e0975dd6a..7c11e1afe9e6 100644 --- a/sound/soc/omap/omap3beagle.c +++ b/sound/soc/omap/omap3beagle.c @@ -33,14 +33,13 @@  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  static int omap3beagle_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int fmt;  	int ret; @@ -92,25 +91,21 @@ static struct snd_soc_ops omap3beagle_ops = {  static struct snd_soc_dai_link omap3beagle_dai = {  	.name = "TWL4030",  	.stream_name = "TWL4030", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.platform_name = "omap-pcm-audio", +	.codec_dai_name = "twl4030-hifi", +	.codec_name = "twl4030-codec",  	.ops = &omap3beagle_ops,  };  /* Audio machine driver */  static struct snd_soc_card snd_soc_omap3beagle = {  	.name = "omap3beagle", -	.platform = &omap_soc_platform, +	.owner = THIS_MODULE,  	.dai_link = &omap3beagle_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device omap3beagle_snd_devdata = { -	.card = &snd_soc_omap3beagle, -	.codec_dev = &soc_codec_dev_twl4030, -}; -  static struct platform_device *omap3beagle_snd_device;  static int __init omap3beagle_soc_init(void) @@ -129,9 +124,7 @@ static int __init omap3beagle_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); -	omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; -	*(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);  	ret = platform_device_add(omap3beagle_snd_device);  	if (ret) diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c index dfcb344092e4..1ac5babef00d 100644 --- a/sound/soc/omap/omap3evm.c +++ b/sound/soc/omap/omap3evm.c @@ -31,14 +31,13 @@  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  static int omap3evm_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -80,32 +79,20 @@ static struct snd_soc_ops omap3evm_ops = {  static struct snd_soc_dai_link omap3evm_dai = {  	.name 		= "TWL4030",  	.stream_name 	= "TWL4030", -	.cpu_dai 	= &omap_mcbsp_dai[0], -	.codec_dai 	= &twl4030_dai[TWL4030_DAI_HIFI], +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.codec_dai_name = "twl4030-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "twl4030-codec",  	.ops 		= &omap3evm_ops,  };  /* Audio machine driver */  static struct snd_soc_card snd_soc_omap3evm = {  	.name = "omap3evm", -	.platform = &omap_soc_platform,  	.dai_link = &omap3evm_dai,  	.num_links = 1,  }; -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { -	.ramp_delay_value = 4, -	.sysclk = 26000, -}; - -/* Audio subsystem */ -static struct snd_soc_device omap3evm_snd_devdata = { -	.card = &snd_soc_omap3evm, -	.codec_dev = &soc_codec_dev_twl4030, -	.codec_data = &twl4030_setup, -}; -  static struct platform_device *omap3evm_snd_device;  static int __init omap3evm_soc_init(void) @@ -124,10 +111,7 @@ static int __init omap3evm_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata); -	omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev; -	*(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; - +	platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);  	ret = platform_device_add(omap3evm_snd_device);  	if (ret)  		goto err1; diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 9eecac135bbb..dbd9d96b5f92 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -31,10 +31,10 @@  #include <sound/soc-dapm.h>  #include <asm/mach-types.h> +#include <plat/mcbsp.h>  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  #define OMAP3_PANDORA_DAC_POWER_GPIO	118  #define OMAP3_PANDORA_AMP_POWER_GPIO	14 @@ -47,8 +47,8 @@ static int omap3pandora_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |  		  SND_SOC_DAIFMT_CBS_CFS;  	int ret; @@ -167,8 +167,9 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = {  	{"Mic Bias 2", NULL, "Mic (external)"},  }; -static int omap3pandora_out_init(struct snd_soc_codec *codec) +static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* All TWL4030 output pins are floating */ @@ -194,8 +195,9 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec)  	return snd_soc_dapm_sync(codec);  } -static int omap3pandora_in_init(struct snd_soc_codec *codec) +static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* Not comnnected */ @@ -224,15 +226,19 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {  	{  		.name = "PCM1773",  		.stream_name = "HiFi Out", -		.cpu_dai = &omap_mcbsp_dai[0], -		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +		.cpu_dai_name = "omap-mcbsp-dai.1", +		.codec_dai_name = "twl4030-hifi", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.ops = &omap3pandora_ops,  		.init = omap3pandora_out_init,  	}, {  		.name = "TWL4030",  		.stream_name = "Line/Mic In", -		.cpu_dai = &omap_mcbsp_dai[1], -		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +		.cpu_dai_name = "omap-mcbsp-dai.3", +		.codec_dai_name = "twl4030-hifi", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.ops = &omap3pandora_ops,  		.init = omap3pandora_in_init,  	} @@ -241,17 +247,10 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {  /* SoC card */  static struct snd_soc_card snd_soc_card_omap3pandora = {  	.name = "omap3pandora", -	.platform = &omap_soc_platform,  	.dai_link = omap3pandora_dai,  	.num_links = ARRAY_SIZE(omap3pandora_dai),  }; -/* Audio subsystem */ -static struct snd_soc_device omap3pandora_snd_data = { -	.card = &snd_soc_card_omap3pandora, -	.codec_dev = &soc_codec_dev_twl4030, -}; -  static struct platform_device *omap3pandora_snd_device;  static int __init omap3pandora_soc_init(void) @@ -294,10 +293,7 @@ static int __init omap3pandora_soc_init(void)  		goto fail1;  	} -	platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); -	omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev; -	*(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */ -	*(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */ +	platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);  	ret = platform_device_add(omap3pandora_snd_device);  	if (ret) { diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 498ca2e03519..f0e662556428 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -55,8 +55,8 @@ static int osk_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int err;  	/* Set codec DAI configuration */ @@ -113,8 +113,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MICIN", NULL, "Mic Jack"},  }; -static int osk_tlv320aic23_init(struct snd_soc_codec *codec) +static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	/* Add osk5912 specific widgets */  	snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, @@ -136,8 +137,10 @@ static int osk_tlv320aic23_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link osk_dai = {  	.name = "TLV320AIC23",  	.stream_name = "AIC23", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &tlv320aic23_dai, +	.cpu_dai_name = "omap-mcbsp-dai.0", +	.codec_dai_name = "tlv320aic23-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "tlv320aic23-codec",  	.init = osk_tlv320aic23_init,  	.ops = &osk_ops,  }; @@ -145,17 +148,10 @@ static struct snd_soc_dai_link osk_dai = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_card_osk = {  	.name = "OSK5912", -	.platform = &omap_soc_platform,  	.dai_link = &osk_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device osk_snd_devdata = { -	.card = &snd_soc_card_osk, -	.codec_dev = &soc_codec_dev_tlv320aic23, -}; -  static struct platform_device *osk_snd_device;  static int __init osk_soc_init(void) @@ -171,9 +167,7 @@ static int __init osk_soc_init(void)  	if (!osk_snd_device)  		return -ENOMEM; -	platform_set_drvdata(osk_snd_device, &osk_snd_devdata); -	osk_snd_devdata.dev = &osk_snd_device->dev; -	*(unsigned int *)osk_dai.cpu_dai->private_data = 0;	/* McBSP1 */ +	platform_set_drvdata(osk_snd_device, &snd_soc_card_osk);  	err = platform_device_add(osk_snd_device);  	if (err)  		goto err1; diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c index c25f5276ad6f..e95a607937de 100644 --- a/sound/soc/omap/overo.c +++ b/sound/soc/omap/overo.c @@ -33,14 +33,13 @@  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  static int overo_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -82,25 +81,20 @@ static struct snd_soc_ops overo_ops = {  static struct snd_soc_dai_link overo_dai = {  	.name = "TWL4030",  	.stream_name = "TWL4030", -	.cpu_dai = &omap_mcbsp_dai[0], -	.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +	.cpu_dai_name = "omap-mcbsp-dai.1", +	.codec_dai_name = "twl4030-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "twl4030-codec",  	.ops = &overo_ops,  };  /* Audio machine driver */  static struct snd_soc_card snd_soc_card_overo = {  	.name = "overo", -	.platform = &omap_soc_platform,  	.dai_link = &overo_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device overo_snd_devdata = { -	.card = &snd_soc_card_overo, -	.codec_dev = &soc_codec_dev_twl4030, -}; -  static struct platform_device *overo_snd_device;  static int __init overo_soc_init(void) @@ -119,9 +113,7 @@ static int __init overo_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(overo_snd_device, &overo_snd_devdata); -	overo_snd_devdata.dev = &overo_snd_device->dev; -	*(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);  	ret = platform_device_add(overo_snd_device);  	if (ret) diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 88052d29617f..d1d8098923ce 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -31,6 +31,7 @@  #include <sound/pcm.h>  #include <sound/soc.h>  #include <sound/soc-dapm.h> +#include <plat/mcbsp.h>  #include <asm/mach-types.h> @@ -76,7 +77,7 @@ static int rx51_startup(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	snd_pcm_hw_constraint_minmax(runtime,  				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); @@ -89,8 +90,8 @@ static int rx51_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int err;  	/* Set codec DAI configuration */ @@ -240,9 +241,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {  		     rx51_get_jack, rx51_set_jack),  }; -static int rx51_aic34_init(struct snd_soc_codec *codec) +static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)  { -	struct snd_soc_card *card = codec->socdev->card; +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* Set up NC codec pins */ @@ -266,7 +267,7 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)  	snd_soc_dapm_sync(codec);  	/* AV jack detection */ -	err = snd_soc_jack_new(card, "AV Jack", +	err = snd_soc_jack_new(codec, "AV Jack",  			       SND_JACK_VIDEOOUT, &rx51_av_jack);  	if (err)  		return err; @@ -282,32 +283,20 @@ static struct snd_soc_dai_link rx51_dai[] = {  	{  		.name = "TLV320AIC34",  		.stream_name = "AIC34", -		.cpu_dai = &omap_mcbsp_dai[0], -		.codec_dai = &aic3x_dai, +		.cpu_dai_name = "omap-mcbsp-dai.1", +		.codec_dai_name = "tlv320aic3x-hifi", +		.platform_name = "omap-pcm-audio", +		.codec_name = "tlv320aic3x-codec.2-0018",  		.init = rx51_aic34_init,  		.ops = &rx51_ops,  	},  }; -/* Audio private data */ -static struct aic3x_setup_data rx51_aic34_setup = { -	.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, -	.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, -}; -  /* Audio card */  static struct snd_soc_card rx51_sound_card = {  	.name = "RX-51",  	.dai_link = rx51_dai,  	.num_links = ARRAY_SIZE(rx51_dai), -	.platform = &omap_soc_platform, -}; - -/* Audio subsystem */ -static struct snd_soc_device rx51_snd_devdata = { -	.card = &rx51_sound_card, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &rx51_aic34_setup,  };  static struct platform_device *rx51_snd_device; @@ -330,9 +319,7 @@ static int __init rx51_soc_init(void)  		goto err1;  	} -	platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); -	rx51_snd_devdata.dev = &rx51_snd_device->dev; -	*(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ +	platform_set_drvdata(rx51_snd_device, &rx51_sound_card);  	err = platform_device_add(rx51_snd_device);  	if (err) diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 3c85c0f92823..76ce77b91844 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -36,9 +36,11 @@  #include <mach/gpio.h>  #include <plat/mcbsp.h> +/* Register descriptions for twl4030 codec part */ +#include <linux/mfd/twl4030-codec.h> +  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  /* TWL4030 PMBR1 Register */  #define TWL4030_INTBR_PMBR1		0x0D @@ -51,8 +53,8 @@ static int sdp3430_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -94,8 +96,8 @@ static int sdp3430_hw_voice_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -186,8 +188,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"Headset Stereophone", NULL, "HSOR"},  }; -static int sdp3430_twl4030_init(struct snd_soc_codec *codec) +static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* Add SDP3430 specific widgets */ @@ -225,7 +228,7 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)  		return ret;  	/* Headset jack detection */ -	ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", +	ret = snd_soc_jack_new(codec, "Headset Jack",  				SND_JACK_HEADSET, &hs_jack);  	if (ret)  		return ret; @@ -241,14 +244,15 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)  	return ret;  } -static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec) +static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	unsigned short reg;  	/* Enable voice interface */ -	reg = codec->read(codec, TWL4030_REG_VOICE_IF); +	reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);  	reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; -	codec->write(codec, TWL4030_REG_VOICE_IF, reg); +	codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);  	return 0;  } @@ -259,16 +263,20 @@ static struct snd_soc_dai_link sdp3430_dai[] = {  	{  		.name = "TWL4030 I2S",  		.stream_name = "TWL4030 Audio", -		.cpu_dai = &omap_mcbsp_dai[0], -		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +		.cpu_dai_name = "omap-mcbsp-dai.1", +		.codec_dai_name = "twl4030-hifi", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.init = sdp3430_twl4030_init,  		.ops = &sdp3430_ops,  	},  	{  		.name = "TWL4030 PCM",  		.stream_name = "TWL4030 Voice", -		.cpu_dai = &omap_mcbsp_dai[1], -		.codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], +		.cpu_dai_name = "omap-mcbsp-dai.2", +		.codec_dai_name = "twl4030-voice", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.init = sdp3430_twl4030_voice_init,  		.ops = &sdp3430_voice_ops,  	}, @@ -277,25 +285,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_sdp3430 = {  	.name = "SDP3430", -	.platform = &omap_soc_platform,  	.dai_link = sdp3430_dai,  	.num_links = ARRAY_SIZE(sdp3430_dai),  }; -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { -	.ramp_delay_value = 3, -	.sysclk = 26000, -	.hs_extmute = 1, -}; - -/* Audio subsystem */ -static struct snd_soc_device sdp3430_snd_devdata = { -	.card = &snd_soc_sdp3430, -	.codec_dev = &soc_codec_dev_twl4030, -	.codec_data = &twl4030_setup, -}; -  static struct platform_device *sdp3430_snd_device;  static int __init sdp3430_soc_init(void) @@ -315,10 +308,7 @@ static int __init sdp3430_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); -	sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; -	*(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ -	*(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ +	platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430);  	/* Set TWL4030 GPIO6 as EXTMUTE signal */  	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index 4ebbde6b565f..62f6a622d791 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c @@ -31,7 +31,6 @@  #include <plat/mux.h>  #include "mcpdm.h" -#include "omap-mcpdm.h"  #include "omap-pcm.h"  #include "../codecs/twl6040.h" @@ -41,7 +40,7 @@ static int sdp4430_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 *codec_dai = rtd->codec_dai;  	int clk_id, freq;  	int ret; @@ -60,6 +59,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,  		printk(KERN_ERR "can't set codec system clock\n");  		return ret;  	} +	return ret;  }  static struct snd_soc_ops sdp4430_ops = { @@ -126,8 +126,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"Earphone Spk", NULL, "EP"},  }; -static int sdp4430_twl6040_init(struct snd_soc_codec *codec) +static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* Add SDP4430 specific controls */ @@ -164,8 +165,10 @@ static int sdp4430_twl6040_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link sdp4430_dai = {  	.name = "TWL6040",  	.stream_name = "TWL6040", -	.cpu_dai = &omap_mcpdm_dai, -	.codec_dai = &twl6040_dai, +	.cpu_dai_name ="omap-mcpdm-dai", +	.codec_dai_name = "twl6040-hifi", +	.platform_name = "omap-pcm-audio", +	.codec_name = "twl6040-codec",  	.init = sdp4430_twl6040_init,  	.ops = &sdp4430_ops,  }; @@ -173,17 +176,10 @@ static struct snd_soc_dai_link sdp4430_dai = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_sdp4430 = {  	.name = "SDP4430", -	.platform = &omap_soc_platform,  	.dai_link = &sdp4430_dai,  	.num_links = 1,  }; -/* Audio subsystem */ -static struct snd_soc_device sdp4430_snd_devdata = { -	.card = &snd_soc_sdp4430, -	.codec_dev = &soc_codec_dev_twl6040, -}; -  static struct platform_device *sdp4430_snd_device;  static int __init sdp4430_soc_init(void) @@ -202,8 +198,7 @@ static int __init sdp4430_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata); -	sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev; +	platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);  	ret = platform_device_add(sdp4430_snd_device);  	if (ret) diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 50a94ee76ecc..338dc9552bd6 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -29,21 +29,23 @@  #include <asm/mach-types.h>  #include <mach/hardware.h>  #include <mach/gpio.h> +#include <mach/board-zoom.h>  #include <plat/mcbsp.h> +/* Register descriptions for twl4030 codec part */ +#include <linux/mfd/twl4030-codec.h> +  #include "omap-mcbsp.h"  #include "omap-pcm.h" -#include "../codecs/twl4030.h"  #define ZOOM2_HEADSET_MUX_GPIO		(OMAP_MAX_GPIO_LINES + 15) -#define ZOOM2_HEADSET_EXTMUTE_GPIO	153  static int zoom2_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -85,8 +87,8 @@ static int zoom2_hw_voice_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set codec DAI configuration */ @@ -157,8 +159,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"Aux In", NULL, "AUXR"},  }; -static int zoom2_twl4030_init(struct snd_soc_codec *codec) +static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* Add Zoom2 specific widgets */ @@ -192,14 +195,15 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec)  	return ret;  } -static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) +static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	unsigned short reg;  	/* Enable voice interface */ -	reg = codec->read(codec, TWL4030_REG_VOICE_IF); +	reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);  	reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; -	codec->write(codec, TWL4030_REG_VOICE_IF, reg); +	codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);  	return 0;  } @@ -209,16 +213,20 @@ static struct snd_soc_dai_link zoom2_dai[] = {  	{  		.name = "TWL4030 I2S",  		.stream_name = "TWL4030 Audio", -		.cpu_dai = &omap_mcbsp_dai[0], -		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], +		.cpu_dai_name = "omap-mcbsp-dai.1", +		.codec_dai_name = "twl4030-hifi", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.init = zoom2_twl4030_init,  		.ops = &zoom2_ops,  	},  	{  		.name = "TWL4030 PCM",  		.stream_name = "TWL4030 Voice", -		.cpu_dai = &omap_mcbsp_dai[1], -		.codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], +		.cpu_dai_name = "omap-mcbsp-dai.2", +		.codec_dai_name = "twl4030-voice", +		.platform_name = "omap-pcm-audio", +		.codec_name = "twl4030-codec",  		.init = zoom2_twl4030_voice_init,  		.ops = &zoom2_voice_ops,  	}, @@ -227,32 +235,10 @@ static struct snd_soc_dai_link zoom2_dai[] = {  /* Audio machine driver */  static struct snd_soc_card snd_soc_zoom2 = {  	.name = "Zoom2", -	.platform = &omap_soc_platform,  	.dai_link = zoom2_dai,  	.num_links = ARRAY_SIZE(zoom2_dai),  }; -/* EXTMUTE callback function */ -void zoom2_set_hs_extmute(int mute) -{ -	gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); -} - -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { -	.ramp_delay_value = 3,	/* 161 ms */ -	.sysclk = 26000, -	.hs_extmute = 1, -	.set_hs_extmute = zoom2_set_hs_extmute, -}; - -/* Audio subsystem */ -static struct snd_soc_device zoom2_snd_devdata = { -	.card = &snd_soc_zoom2, -	.codec_dev = &soc_codec_dev_twl4030, -	.codec_data = &twl4030_setup, -}; -  static struct platform_device *zoom2_snd_device;  static int __init zoom2_soc_init(void) @@ -271,11 +257,7 @@ static int __init zoom2_soc_init(void)  		return -ENOMEM;  	} -	platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); -	zoom2_snd_devdata.dev = &zoom2_snd_device->dev; -	*(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ -	*(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - +	platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2);  	ret = platform_device_add(zoom2_snd_device);  	if (ret)  		goto err1; diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index fefe1a57f31a..11c6a495f970 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -99,7 +99,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec)  static int corgi_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	/* check the jack status at stream startup */  	corgi_ext_control(codec); @@ -118,8 +118,8 @@ static int corgi_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0; @@ -272,8 +272,9 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {  /*   * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device   */ -static int corgi_wm8731_init(struct snd_soc_codec *codec) +static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	snd_soc_dapm_nc_pin(codec, "LLINEIN"); @@ -300,8 +301,10 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link corgi_dai = {  	.name = "WM8731",  	.stream_name = "WM8731", -	.cpu_dai = &pxa_i2s_dai, -	.codec_dai = &wm8731_dai, +	.cpu_dai_name = "pxa-is2-dai", +	.codec_dai_name = "wm8731-hifi", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm8731-codec-0.001a",  	.init = corgi_wm8731_init,  	.ops = &corgi_ops,  }; @@ -309,17 +312,10 @@ static struct snd_soc_dai_link corgi_dai = {  /* corgi audio machine driver */  static struct snd_soc_card snd_soc_corgi = {  	.name = "Corgi", -	.platform = &pxa2xx_soc_platform,  	.dai_link = &corgi_dai,  	.num_links = 1,  }; -/* corgi audio subsystem */ -static struct snd_soc_device corgi_snd_devdata = { -	.card = &snd_soc_corgi, -	.codec_dev = &soc_codec_dev_wm8731, -}; -  static struct platform_device *corgi_snd_device;  static int __init corgi_init(void) @@ -334,8 +330,7 @@ static int __init corgi_init(void)  	if (!corgi_snd_device)  		return -ENOMEM; -	platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata); -	corgi_snd_devdata.dev = &corgi_snd_device->dev; +	platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);  	ret = platform_device_add(corgi_snd_device);  	if (ret) diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 7cd2f89d7b10..f614607b2055 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -24,7 +24,6 @@  #include <asm/mach-types.h>  #include "../codecs/wm9705.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h" @@ -90,8 +89,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"Mic Amp", NULL, "Mic (Internal)"},  }; -static int e740_ac97_init(struct snd_soc_codec *codec) +static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_nc_pin(codec, "HPOUTL");  	snd_soc_dapm_nc_pin(codec, "HPOUTR");  	snd_soc_dapm_nc_pin(codec, "PHONE"); @@ -116,30 +117,28 @@ static struct snd_soc_dai_link e740_dai[] = {  	{  		.name = "AC97",  		.stream_name = "AC97 HiFi", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], +		.cpu_dai_name = "pxa-ac97.0", +		.codec_dai_name = "wm9705-hifi", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9705-codec",  		.init = e740_ac97_init,  	},  	{  		.name = "AC97 Aux",  		.stream_name = "AC97 Aux", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], +		.cpu_dai_name = "pxa-ac97.1", +		.codec_dai_name = "wm9705-aux", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9705-codec",  	},  };  static struct snd_soc_card e740 = {  	.name = "Toshiba e740", -	.platform = &pxa2xx_soc_platform,  	.dai_link = e740_dai,  	.num_links = ARRAY_SIZE(e740_dai),  }; -static struct snd_soc_device e740_snd_devdata = { -	.card = &e740, -	.codec_dev = &soc_codec_dev_wm9705, -}; -  static struct platform_device *e740_snd_device;  static int __init e740_init(void) @@ -178,8 +177,7 @@ static int __init e740_init(void)  		goto free_apwr_gpio;  	} -	platform_set_drvdata(e740_snd_device, &e740_snd_devdata); -	e740_snd_devdata.dev = &e740_snd_device->dev; +	platform_set_drvdata(e740_snd_device, &e740);  	ret = platform_device_add(e740_snd_device);  	if (!ret) diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 8dceccc5e059..4c143803a75e 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -24,7 +24,6 @@  #include <asm/mach-types.h>  #include "../codecs/wm9705.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, @@ -72,8 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MIC1", NULL, "Mic (Internal)"},  }; -static int e750_ac97_init(struct snd_soc_codec *codec) +static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_nc_pin(codec, "LOUT");  	snd_soc_dapm_nc_pin(codec, "ROUT");  	snd_soc_dapm_nc_pin(codec, "PHONE"); @@ -98,31 +99,29 @@ static struct snd_soc_dai_link e750_dai[] = {  	{  		.name = "AC97",  		.stream_name = "AC97 HiFi", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], +		.cpu_dai_name = "pxa-ac97.0", +		.codec_dai_name = "wm9705-hifi", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9705-codec",  		.init = e750_ac97_init,  		/* use ops to check startup state */  	},  	{  		.name = "AC97 Aux",  		.stream_name = "AC97 Aux", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -		.codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], +		.cpu_dai_name = "pxa-ac97.1", +		.codec_dai_name ="wm9705-aux", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9705-codec",  	},  };  static struct snd_soc_card e750 = {  	.name = "Toshiba e750", -	.platform = &pxa2xx_soc_platform,  	.dai_link = e750_dai,  	.num_links = ARRAY_SIZE(e750_dai),  }; -static struct snd_soc_device e750_snd_devdata = { -	.card = &e750, -	.codec_dev = &soc_codec_dev_wm9705, -}; -  static struct platform_device *e750_snd_device;  static int __init e750_init(void) @@ -154,8 +153,7 @@ static int __init e750_init(void)  		goto free_spk_amp_gpio;  	} -	platform_set_drvdata(e750_snd_device, &e750_snd_devdata); -	e750_snd_devdata.dev = &e750_snd_device->dev; +	platform_set_drvdata(e750_snd_device, &e750);  	ret = platform_device_add(e750_snd_device);  	if (!ret) diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index bc019cdce429..d42e5fe832c5 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -23,7 +23,6 @@  #include <mach/eseries-gpio.h>  #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, @@ -73,8 +72,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"MIC2", NULL, "Mic (Internal2)"},  }; -static int e800_ac97_init(struct snd_soc_codec *codec) +static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_new_controls(codec, e800_dapm_widgets,  					ARRAY_SIZE(e800_dapm_widgets)); @@ -88,30 +89,28 @@ static struct snd_soc_dai_link e800_dai[] = {  	{  		.name = "AC97",  		.stream_name = "AC97 HiFi", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], +		.cpu_dai_name = "pxa-ac97.0", +		.codec_dai_name = "wm9712-hifi", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9712-codec",  		.init = e800_ac97_init,  	},  	{  		.name = "AC97 Aux",  		.stream_name = "AC97 Aux", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], +		.cpu_dai_name = "pxa-ac97.1", +		.codec_dai_name ="wm9712-aux", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9712-codec",  	},  };  static struct snd_soc_card e800 = {  	.name = "Toshiba e800", -	.platform = &pxa2xx_soc_platform,  	.dai_link = e800_dai,  	.num_links = ARRAY_SIZE(e800_dai),  }; -static struct snd_soc_device e800_snd_devdata = { -	.card = &e800, -	.codec_dev = &soc_codec_dev_wm9712, -}; -  static struct platform_device *e800_snd_device;  static int __init e800_init(void) @@ -141,8 +140,7 @@ static int __init e800_init(void)  	if (!e800_snd_device)  		return -ENOMEM; -	platform_set_drvdata(e800_snd_device, &e800_snd_devdata); -	e800_snd_devdata.dev = &e800_snd_device->dev; +	platform_set_drvdata(e800_snd_device, &e800);  	ret = platform_device_add(e800_snd_device);  	if (!ret) diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index f4756e4025fd..7046128b2a4c 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -39,29 +39,27 @@ static struct snd_soc_dai_link em_x270_dai[] = {  	{  		.name = "AC97",  		.stream_name = "AC97 HiFi", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], +		.cpu_dai_name = "pxa-ac97.0", +		.codec_dai_name = "wm9712-hifi", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9712-codec",  	},  	{  		.name = "AC97 Aux",  		.stream_name = "AC97 Aux", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -		.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], +		.cpu_dai_name = "pxa-ac97.1", +		.codec_dai_name ="wm9712-aux", +		.platform_name = "pxa-pcm-audio", +		.codec_name = "wm9712-codec",  	},  };  static struct snd_soc_card em_x270 = {  	.name = "EM-X270", -	.platform = &pxa2xx_soc_platform,  	.dai_link = em_x270_dai,  	.num_links = ARRAY_SIZE(em_x270_dai),  }; -static struct snd_soc_device em_x270_snd_devdata = { -	.card = &em_x270, -	.codec_dev = &soc_codec_dev_wm9712, -}; -  static struct platform_device *em_x270_snd_device;  static int __init em_x270_init(void) @@ -76,8 +74,7 @@ static int __init em_x270_init(void)  	if (!em_x270_snd_device)  		return -ENOMEM; -	platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata); -	em_x270_snd_devdata.dev = &em_x270_snd_device->dev; +	platform_set_drvdata(em_x270_snd_device, &em_x270);  	ret = platform_device_add(em_x270_snd_device);  	if (ret) diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c index 405587a01160..03765fc5ac74 100644 --- a/sound/soc/pxa/imote2.c +++ b/sound/soc/pxa/imote2.c @@ -6,14 +6,13 @@  #include "../codecs/wm8940.h"  #include "pxa2xx-i2s.h" -#include "pxa2xx-pcm.h"  static int imote2_asoc_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret; @@ -64,23 +63,19 @@ static struct snd_soc_ops imote2_asoc_ops = {  static struct snd_soc_dai_link imote2_dai = {  	.name = "WM8940",  	.stream_name = "WM8940", -	.cpu_dai = &pxa_i2s_dai, -	.codec_dai = &wm8940_dai, +	.cpu_dai_name = "pxa-i2s", +	.codec_dai_name = "wm8940-hifi", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm8940-codec.0-0034",  	.ops = &imote2_asoc_ops,  };  static struct snd_soc_card snd_soc_imote2 = {  	.name = "Imote2", -	.platform = &pxa2xx_soc_platform,  	.dai_link = &imote2_dai,  	.num_links = 1,  }; -static struct snd_soc_device imote2_snd_devdata = { -	.card = &snd_soc_imote2, -	.codec_dev = &soc_codec_dev_wm8940, -}; -  static struct platform_device *imote2_snd_device;  static int __init imote2_asoc_init(void) @@ -93,8 +88,7 @@ static int __init imote2_asoc_init(void)  	if (!imote2_snd_device)  		return -ENOMEM; -	platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata); -	imote2_snd_devdata.dev = &imote2_snd_device->dev; +	platform_set_drvdata(imote2_snd_device, &snd_soc_imote2);  	ret = platform_device_add(imote2_snd_device);  	if (ret)  		platform_device_put(imote2_snd_device); diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 4c8d99a8d386..608bc3dd835f 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -32,7 +32,6 @@  #include <mach/magician.h>  #include <asm/mach-types.h>  #include "../codecs/uda1380.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-i2s.h"  #include "pxa-ssp.h" @@ -71,7 +70,7 @@ static void magician_ext_control(struct snd_soc_codec *codec)  static int magician_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	/* check the jack status at stream startup */  	magician_ext_control(codec); @@ -86,8 +85,8 @@ static int magician_playback_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int acps, acds, width, rate;  	unsigned int div4 = PXA_SSP_CLK_SCDB_4;  	int ret = 0; @@ -227,8 +226,8 @@ static int magician_capture_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret = 0;  	/* set codec DAI configuration */ @@ -393,8 +392,9 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = {  /*   * Logic for a uda1380 as connected on a HTC Magician   */ -static int magician_uda1380_init(struct snd_soc_codec *codec) +static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* NC codec pins */ @@ -427,16 +427,20 @@ static struct snd_soc_dai_link magician_dai[] = {  {  	.name = "uda1380",  	.stream_name = "UDA1380 Playback", -	.cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], -	.codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK], +	.cpu_dai_name = "pxa-ssp-dai.0", +	.codec_dai_name = "uda1380-hifi-playback", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "uda1380-codec.0-0018",  	.init = magician_uda1380_init,  	.ops = &magician_playback_ops,  },  {  	.name = "uda1380",  	.stream_name = "UDA1380 Capture", -	.cpu_dai = &pxa_i2s_dai, -	.codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE], +	.cpu_dai_name = "pxa-i2s", +	.codec_dai_name = "uda1380-hifi-capture", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "uda1380-codec.0-0018",  	.ops = &magician_capture_ops,  }  }; @@ -446,13 +450,7 @@ static struct snd_soc_card snd_soc_card_magician = {  	.name = "Magician",  	.dai_link = magician_dai,  	.num_links = ARRAY_SIZE(magician_dai), -	.platform = &pxa2xx_soc_platform, -}; -/* magician audio subsystem */ -static struct snd_soc_device magician_snd_devdata = { -	.card = &snd_soc_card_magician, -	.codec_dev = &soc_codec_dev_uda1380,  };  static struct platform_device *magician_snd_device; @@ -514,8 +512,7 @@ static int __init magician_init(void)  		goto err_pdev;  	} -	platform_set_drvdata(magician_snd_device, &magician_snd_devdata); -	magician_snd_devdata.dev = &magician_snd_device->dev; +	platform_set_drvdata(magician_snd_device, &snd_soc_card_magician);  	ret = platform_device_add(magician_snd_device);  	if (ret) {  		platform_device_put(magician_snd_device); diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 19eda8bbfdaf..f284cc54bc80 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -54,7 +54,6 @@  #include <sound/initval.h>  #include <sound/ac97_codec.h> -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  #include "../codecs/wm9713.h" @@ -128,8 +127,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"Rear Speaker", NULL, "SPKR"},  }; -static int mioa701_wm9713_init(struct snd_soc_codec *codec) +static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	unsigned short reg;  	/* Add mioa701 specific widgets */ @@ -139,12 +139,12 @@ static int mioa701_wm9713_init(struct snd_soc_codec *codec)  	snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map));  	/* Prepare GPIO8 for rear speaker amplifier */ -	reg = codec->read(codec, AC97_GPIO_CFG); -	codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); +	reg = codec->driver->read(codec, AC97_GPIO_CFG); +	codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100);  	/* Prepare MIC input */ -	reg = codec->read(codec, AC97_3D_CONTROL); -	codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); +	reg = codec->driver->read(codec, AC97_3D_CONTROL); +	codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000);  	snd_soc_dapm_enable_pin(codec, "Front Speaker");  	snd_soc_dapm_enable_pin(codec, "Rear Speaker"); @@ -162,32 +162,30 @@ static struct snd_soc_dai_link mioa701_dai[] = {  	{  		.name = "AC97",  		.stream_name = "AC97 HiFi", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -		.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], +		.cpu_dai_name = "pxa-ac97.0", +		.codec_dai_name = "wm9713-hifi", +		.codec_name = "wm9713-codec",  		.init = mioa701_wm9713_init, +		.platform_name = "pxa-pcm-audio",  		.ops = &mioa701_ops,  	},  	{  		.name = "AC97 Aux",  		.stream_name = "AC97 Aux", -		.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -		.codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], +		.cpu_dai_name = "pxa-ac97.1", +		.codec_dai_name ="wm9713-aux", +		.codec_name = "wm9713-codec", +		.platform_name = "pxa-pcm-audio",  		.ops = &mioa701_ops,  	},  };  static struct snd_soc_card mioa701 = {  	.name = "MioA701", -	.platform = &pxa2xx_soc_platform,  	.dai_link = mioa701_dai,  	.num_links = ARRAY_SIZE(mioa701_dai),  }; -static struct snd_soc_device mioa701_snd_devdata = { -	.card = &mioa701, -	.codec_dev = &soc_codec_dev_wm9713, -}; -  static struct platform_device *mioa701_snd_device;  static int mioa701_wm9713_probe(struct platform_device *pdev) @@ -205,8 +203,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)  	if (!mioa701_snd_device)  		return -ENOMEM; -	platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); -	mioa701_snd_devdata.dev = &mioa701_snd_device->dev; +	platform_set_drvdata(mioa701_snd_device, &mioa701);  	ret = platform_device_add(mioa701_snd_device);  	if (!ret) diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 1f96e3227be5..13f6d485d571 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -29,7 +29,6 @@  #include <mach/palmasoc.h>  #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  static struct snd_soc_jack hs_jack; @@ -75,8 +74,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  static struct snd_soc_card palm27x_asoc; -static int palm27x_ac97_init(struct snd_soc_codec *codec) +static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* add palm27x specific widgets */ @@ -112,7 +112,7 @@ static int palm27x_ac97_init(struct snd_soc_codec *codec)  		return err;  	/* Jack detection API stuff */ -	err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", +	err = snd_soc_jack_new(codec, "Headphone Jack",  				SND_JACK_HEADPHONE, &hs_jack);  	if (err)  		return err; @@ -132,30 +132,28 @@ static struct snd_soc_dai_link palm27x_dai[] = {  {  	.name = "AC97 HiFi",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], +	.cpu_dai_name = "pxa-ac97.0", +	.codec_dai_name =  "wm9712-hifi", +	.codec_name = "wm9712-codec", +	.platform_name = "pxa-pcm-audio",  	.init = palm27x_ac97_init,  },  {  	.name = "AC97 Aux",  	.stream_name = "AC97 Aux", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], +	.cpu_dai_name = "pxa-ac97.1", +	.codec_dai_name = "wm9712-aux", +	.codec_name = "wm9712-codec", +	.platform_name = "pxa-pcm-audio",  },  };  static struct snd_soc_card palm27x_asoc = {  	.name = "Palm/PXA27x", -	.platform = &pxa2xx_soc_platform,  	.dai_link = palm27x_dai,  	.num_links = ARRAY_SIZE(palm27x_dai),  }; -static struct snd_soc_device palm27x_snd_devdata = { -	.card = &palm27x_asoc, -	.codec_dev = &soc_codec_dev_wm9712, -}; -  static struct platform_device *palm27x_snd_device;  static int palm27x_asoc_probe(struct platform_device *pdev) @@ -178,8 +176,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev)  	if (!palm27x_snd_device)  		return -ENOMEM; -	platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); -	palm27x_snd_devdata.dev = &palm27x_snd_device->dev; +	platform_set_drvdata(palm27x_snd_device, &palm27x_asoc);  	ret = platform_device_add(palm27x_snd_device);  	if (ret != 0) diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c5f36e0eab58..3ba5a962ecb8 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -31,7 +31,6 @@  #include <mach/audio.h>  #include "../codecs/wm8731.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-i2s.h"  #define POODLE_HP        1 @@ -76,7 +75,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec)  static int poodle_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	/* check the jack status at stream startup */  	poodle_ext_control(codec); @@ -97,8 +96,8 @@ static int poodle_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0; @@ -237,8 +236,9 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = {  /*   * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device   */ -static int poodle_wm8731_init(struct snd_soc_codec *codec) +static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	snd_soc_dapm_nc_pin(codec, "LLINEIN"); @@ -266,8 +266,10 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link poodle_dai = {  	.name = "WM8731",  	.stream_name = "WM8731", -	.cpu_dai = &pxa_i2s_dai, -	.codec_dai = &wm8731_dai, +	.cpu_dai_name = "pxa-i2s", +	.codec_dai_name = "wm8731-hifi" +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm8731-codec.0-001a",  	.init = poodle_wm8731_init,  	.ops = &poodle_ops,  }; @@ -275,15 +277,9 @@ static struct snd_soc_dai_link poodle_dai = {  /* poodle audio machine driver */  static struct snd_soc_card snd_soc_poodle = {  	.name = "Poodle", -	.platform = &pxa2xx_soc_platform,  	.dai_link = &poodle_dai,  	.num_links = 1, -}; - -/* poodle audio subsystem */ -static struct snd_soc_device poodle_snd_devdata = { -	.card = &snd_soc_poodle, -	.codec_dev = &soc_codec_dev_wm8731, +	.owner = THIS_MODULE,  };  static struct platform_device *poodle_snd_device; @@ -307,8 +303,7 @@ static int __init poodle_init(void)  	if (!poodle_snd_device)  		return -ENOMEM; -	platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata); -	poodle_snd_devdata.dev = &poodle_snd_device->dev; +	platform_set_drvdata(poodle_snd_device, &snd_soc_poodle);  	ret = platform_device_add(poodle_snd_device);  	if (ret) diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index a1fd23e0e3d0..99d80e85621c 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)  }  static int pxa_ssp_startup(struct snd_pcm_substream *substream, -			   struct snd_soc_dai *dai) +			   struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	int ret = 0; @@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,  }  static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, -			     struct snd_soc_dai *dai) +			     struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	if (!cpu_dai->active) { @@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,  static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	if (!cpu_dai->active) @@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)  static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; @@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp)  static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,  	int clk_id, unsigned int freq, int dir)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	int val; @@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,  static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,  	int div_id, int div)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	int val; @@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,  static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,  	int source, unsigned int freq_in, unsigned int freq_out)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; @@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,  static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,  	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	u32 sscr0; @@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,  static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,  	int tristate)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	u32 sscr1; @@ -464,7 +460,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,  static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,  		unsigned int fmt)  { -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	u32 sscr0;  	u32 sscr1; @@ -555,11 +551,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,   */  static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,  				struct snd_pcm_hw_params *params, -				struct snd_soc_dai *dai) +				struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	int chn = params_channels(params);  	u32 sscr0; @@ -568,7 +562,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,  	int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;  	struct pxa2xx_pcm_dma_params *dma_data; -	dma_data = snd_soc_dai_get_dma_data(dai, substream); +	dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);  	/* generate correct DMA params */  	kfree(dma_data); @@ -581,7 +575,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,  			((chn == 2) && (ttsa != 1)) || (width == 32),  			substream->stream == SNDRV_PCM_STREAM_PLAYBACK); -	snd_soc_dai_set_dma_data(dai, substream, dma_data); +	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);  	/* we can only change the settings if the port is not in use */  	if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) @@ -668,12 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,  }  static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, -			   struct snd_soc_dai *dai) +			   struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;  	int ret = 0; -	struct ssp_priv *priv = cpu_dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);  	struct ssp_device *ssp = priv->ssp;  	int val; @@ -729,8 +721,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,  	return ret;  } -static int pxa_ssp_probe(struct platform_device *pdev, -			    struct snd_soc_dai *dai) +static int pxa_ssp_probe(struct snd_soc_dai *dai)  {  	struct ssp_priv *priv;  	int ret; @@ -746,7 +737,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,  	}  	priv->dai_fmt = (unsigned int) -1; -	dai->private_data = priv; +	snd_soc_dai_set_drvdata(dai, priv);  	return 0; @@ -755,11 +746,12 @@ err_priv:  	return ret;  } -static void pxa_ssp_remove(struct platform_device *pdev, -			      struct snd_soc_dai *dai) +static int pxa_ssp_remove(struct snd_soc_dai *dai)  { -	struct ssp_priv *priv = dai->private_data; +	struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai); +  	pxa_ssp_free(priv->ssp); +	return 0;  }  #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ @@ -784,10 +776,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = {  	.set_tristate	= pxa_ssp_set_dai_tristate,  }; -struct snd_soc_dai pxa_ssp_dai[] = { -	{ -		.name = "pxa2xx-ssp1", -		.id = 0, +static struct snd_soc_dai_driver pxa_ssp_dai = {  		.probe = pxa_ssp_probe,  		.remove = pxa_ssp_remove,  		.suspend = pxa_ssp_suspend, @@ -805,81 +794,38 @@ struct snd_soc_dai pxa_ssp_dai[] = {  			.formats = PXA_SSP_FORMATS,  		 },  		.ops = &pxa_ssp_dai_ops, +}; + +static __devinit int asoc_ssp_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai); +} + +static int __devexit asoc_ssp_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver asoc_ssp_driver = { +	.driver = { +			.name = "pxa-ssp-dai", +			.owner = THIS_MODULE,  	}, -	{	.name = "pxa2xx-ssp2", -		.id = 1, -		.probe = pxa_ssp_probe, -		.remove = pxa_ssp_remove, -		.suspend = pxa_ssp_suspend, -		.resume = pxa_ssp_resume, -		.playback = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		}, -		.capture = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		 }, -		.ops = &pxa_ssp_dai_ops, -	}, -	{ -		.name = "pxa2xx-ssp3", -		.id = 2, -		.probe = pxa_ssp_probe, -		.remove = pxa_ssp_remove, -		.suspend = pxa_ssp_suspend, -		.resume = pxa_ssp_resume, -		.playback = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		}, -		.capture = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		 }, -		.ops = &pxa_ssp_dai_ops, -	}, -	{ -		.name = "pxa2xx-ssp4", -		.id = 3, -		.probe = pxa_ssp_probe, -		.remove = pxa_ssp_remove, -		.suspend = pxa_ssp_suspend, -		.resume = pxa_ssp_resume, -		.playback = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		}, -		.capture = { -			.channels_min = 1, -			.channels_max = 8, -			.rates = PXA_SSP_RATES, -			.formats = PXA_SSP_FORMATS, -		 }, -		.ops = &pxa_ssp_dai_ops, -	}, + +	.probe = asoc_ssp_probe, +	.remove = __devexit_p(asoc_ssp_remove),  }; -EXPORT_SYMBOL_GPL(pxa_ssp_dai);  static int __init pxa_ssp_init(void)  { -	return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); +	return platform_driver_register(&asoc_ssp_driver);  }  module_init(pxa_ssp_init);  static void __exit pxa_ssp_exit(void)  { -	snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); +	platform_driver_unregister(&asoc_ssp_driver);  }  module_exit(pxa_ssp_exit); diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h index 91deadd55675..bc79da221c0d 100644 --- a/sound/soc/pxa/pxa-ssp.h +++ b/sound/soc/pxa/pxa-ssp.h @@ -42,6 +42,4 @@  #define PXA_SSP_PLL_OUT  0 -extern struct snd_soc_dai pxa_ssp_dai[4]; -  #endif diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index d314115e3dd7..9c2bafa112ad 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -104,24 +104,21 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)  #define pxa2xx_ac97_resume	NULL  #endif -static int pxa2xx_ac97_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)  {  	return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));  } -static void pxa2xx_ac97_remove(struct platform_device *pdev, -			       struct snd_soc_dai *dai) +static int pxa2xx_ac97_remove(struct snd_soc_dai *dai)  {  	pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); +	return 0;  }  static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params, -				 struct snd_soc_dai *dai) +				 struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;  	struct pxa2xx_pcm_dma_params *dma_data;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -136,10 +133,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,  static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,  				     struct snd_pcm_hw_params *params, -				     struct snd_soc_dai *dai) +				     struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;  	struct pxa2xx_pcm_dma_params *dma_data;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -154,11 +149,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,  static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,  				     struct snd_pcm_hw_params *params, -				     struct snd_soc_dai *dai) +				     struct snd_soc_dai *cpu_dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)  		return -ENODEV;  	else @@ -188,10 +180,9 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {   * There is only 1 physical AC97 interface for pxa2xx, but it   * has extra fifo's that can be used for aux DACs and ADCs.   */ -struct snd_soc_dai pxa_ac97_dai[] = { +static struct snd_soc_dai_driver pxa_ac97_dai[] = {  {  	.name = "pxa2xx-ac97", -	.id = 0,  	.ac97_control = 1,  	.probe = pxa2xx_ac97_probe,  	.remove = pxa2xx_ac97_remove, @@ -213,7 +204,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {  },  {  	.name = "pxa2xx-ac97-aux", -	.id = 1,  	.ac97_control = 1,  	.playback = {  		.stream_name = "AC97 Aux Playback", @@ -231,7 +221,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {  },  {  	.name = "pxa2xx-ac97-mic", -	.id = 2,  	.ac97_control = 1,  	.capture = {  		.stream_name = "AC97 Mic Capture", @@ -243,36 +232,26 @@ struct snd_soc_dai pxa_ac97_dai[] = {  },  }; -EXPORT_SYMBOL_GPL(pxa_ac97_dai);  EXPORT_SYMBOL_GPL(soc_ac97_ops); -static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) +static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)  { -	int i; -	pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; - -	if (pdev->id >= 0) { +	if (pdev->id != -1) {  		dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");  		return -ENXIO;  	} -	for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) { -		pxa_ac97_dai[i].dev = &pdev->dev; -		if (pdata && pdata->codec_pdata[0]) -			pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0]; -	} -  	/* 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)); +	return snd_soc_register_dais(&pdev->dev, 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)); - +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));  	return 0;  } diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h index e390de8edcd4..eda891e6f31b 100644 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ b/sound/soc/pxa/pxa2xx-ac97.h @@ -14,8 +14,6 @@  #define PXA2XX_DAI_AC97_AUX		1  #define PXA2XX_DAI_AC97_MIC		2 -extern struct snd_soc_dai pxa_ac97_dai[3]; -  /* platform data */  extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index c1a5275721e4..3b473b200a8f 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -80,6 +80,7 @@ struct pxa_i2s_port {  };  static struct pxa_i2s_port pxa_i2s;  static struct clk *clk_i2s; +static int clk_ena = 0;  static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {  	.name			= "I2S PCM Stereo out", @@ -101,7 +102,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,  			      struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	if (IS_ERR(clk_i2s))  		return PTR_ERR(clk_i2s); @@ -162,13 +163,11 @@ static int pxa2xx_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; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;  	struct pxa2xx_pcm_dma_params *dma_data;  	BUG_ON(IS_ERR(clk_i2s));  	clk_enable(clk_i2s); -	dai->private_data = dai; +	clk_ena = 1;  	pxa_i2s_wait();  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -176,7 +175,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,  	else  		dma_data = &pxa2xx_i2s_pcm_stereo_in; -	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); +	snd_soc_dai_set_dma_data(dai, substream, dma_data);  	/* is port used by another stream */  	if (!(SACR0 & SACR0_ENB)) { @@ -259,9 +258,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,  	if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {  		SACR0 &= ~SACR0_ENB;  		pxa_i2s_wait(); -		if (dai->private_data != NULL) { +		if (clk_ena) {  			clk_disable(clk_i2s); -			dai->private_data = NULL; +			clk_ena = 0;  		}  	}  } @@ -300,6 +299,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)  #define pxa2xx_i2s_resume	NULL  #endif +static int pxa2xx_i2s_probe(struct snd_soc_dai *dai) +{ +	clk_i2s = clk_get(dai->dev, "I2SCLK"); +	if (IS_ERR(clk_i2s)) +		return PTR_ERR(clk_i2s); + +	/* +	 * PXA Developer's Manual: +	 * If SACR0[ENB] is toggled in the middle of a normal operation, +	 * the SACR0[RST] bit must also be set and cleared to reset all +	 * I2S controller registers. +	 */ +	SACR0 = SACR0_RST; +	SACR0 = 0; +	/* Make sure RPL and REC are disabled */ +	SACR1 = SACR1_DRPL | SACR1_DREC; +	/* Along with FIFO servicing */ +	SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); + +	return 0; +} + +static int  pxa2xx_i2s_remove(struct snd_soc_dai *dai) +{ +	clk_put(clk_i2s); +	clk_i2s = ERR_PTR(-ENOENT); +	return 0; +} +  #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\  		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \  		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) @@ -313,9 +341,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = {  	.set_sysclk	= pxa2xx_i2s_set_dai_sysclk,  }; -struct snd_soc_dai pxa_i2s_dai = { -	.name = "pxa2xx-i2s", -	.id = 0, +static struct snd_soc_dai_driver pxa_i2s_dai = { +	.probe = pxa2xx_i2s_probe, +	.remove = pxa2xx_i2s_remove,  	.suspend = pxa2xx_i2s_suspend,  	.resume = pxa2xx_i2s_resume,  	.playback = { @@ -332,49 +360,20 @@ struct snd_soc_dai pxa_i2s_dai = {  	.symmetric_rates = 1,  }; -EXPORT_SYMBOL_GPL(pxa_i2s_dai); - -static int pxa2xx_i2s_probe(struct platform_device *dev) +static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)  { -	int ret; - -	clk_i2s = clk_get(&dev->dev, "I2SCLK"); -	if (IS_ERR(clk_i2s)) -		return PTR_ERR(clk_i2s); - -	pxa_i2s_dai.dev = &dev->dev; -	pxa_i2s_dai.private_data = NULL; -	ret = snd_soc_register_dai(&pxa_i2s_dai); -	if (ret != 0) -		clk_put(clk_i2s); - -	/* -	 * PXA Developer's Manual: -	 * If SACR0[ENB] is toggled in the middle of a normal operation, -	 * the SACR0[RST] bit must also be set and cleared to reset all -	 * I2S controller registers. -	 */ -	SACR0 = SACR0_RST; -	SACR0 = 0; -	/* Make sure RPL and REC are disabled */ -	SACR1 = SACR1_DRPL | SACR1_DREC; -	/* Along with FIFO servicing */ -	SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); - -	return ret; +	return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);  } -static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) +static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&pxa_i2s_dai); -	clk_put(clk_i2s); -	clk_i2s = ERR_PTR(-ENOENT); +	snd_soc_unregister_dai(&pdev->dev);  	return 0;  }  static struct platform_driver pxa2xx_i2s_driver = { -	.probe = pxa2xx_i2s_probe, -	.remove = __devexit_p(pxa2xx_i2s_remove), +	.probe = pxa2xx_i2s_drv_probe, +	.remove = __devexit_p(pxa2xx_i2s_drv_remove),  	.driver = {  		.name = "pxa2xx-i2s", diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h index e2def441153e..070f3c6059fe 100644 --- a/sound/soc/pxa/pxa2xx-i2s.h +++ b/sound/soc/pxa/pxa2xx-i2s.h @@ -15,6 +15,4 @@  /* I2S clock */  #define PXA2XX_I2S_SYSCLK		0 -extern struct snd_soc_dai pxa_i2s_dai; -  #endif diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index adc7e6f15f93..5127044acfec 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -28,7 +28,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,  	struct pxa2xx_pcm_dma_params *dma;  	int ret; -	dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +	dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	/* return if this is a bufferless transfer e.g.  	 * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = DMA_BIT_MASK(32); -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -112,25 +112,44 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  	return ret;  } -struct snd_soc_platform pxa2xx_soc_platform = { -	.name		= "pxa2xx-audio", -	.pcm_ops 	= &pxa2xx_pcm_ops, +static struct snd_soc_platform_driver pxa2xx_soc_platform = { +	.ops 	= &pxa2xx_pcm_ops,  	.pcm_new	= pxa2xx_soc_pcm_new,  	.pcm_free	= pxa2xx_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); -static int __init pxa2xx_soc_platform_init(void) +static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&pxa2xx_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);  } -module_init(pxa2xx_soc_platform_init); -static void __exit pxa2xx_soc_platform_exit(void) +static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&pxa2xx_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver pxa_pcm_driver = { +	.driver = { +			.name = "pxa-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = pxa2xx_soc_platform_probe, +	.remove = __devexit_p(pxa2xx_soc_platform_remove), +}; + +static int __init snd_pxa_pcm_init(void) +{ +	return platform_driver_register(&pxa_pcm_driver); +} +module_init(snd_pxa_pcm_init); + +static void __exit snd_pxa_pcm_exit(void) +{ +	platform_driver_unregister(&pxa_pcm_driver);  } -module_exit(pxa2xx_soc_platform_exit); +module_exit(snd_pxa_pcm_exit);  MODULE_AUTHOR("Nicolas Pitre");  MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h deleted file mode 100644 index 60c3b20aeeb4..000000000000 --- a/sound/soc/pxa/pxa2xx-pcm.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip - * - * Author:	Nicolas Pitre - * Created:	Nov 30, 2004 - * Copyright:	MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _PXA2XX_PCM_H -#define _PXA2XX_PCM_H - -/* platform data */ -extern struct snd_soc_platform pxa2xx_soc_platform; - -#endif diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 7e3f41696c41..2cda82bc5d2e 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c @@ -26,9 +26,6 @@  #include <asm/mach-types.h> -#include "../codecs/cs4270.h" -#include "../codecs/ak4104.h" -#include "pxa2xx-pcm.h"  #include "pxa-ssp.h"  #define GPIO_SPDIF_RESET	(38) @@ -71,7 +68,7 @@ static void raumfeld_enable_audio(bool en)  static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	/* set freq to 0 to enable all possible codec sample rates */  	return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); @@ -80,7 +77,7 @@ static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)  static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	/* set freq to 0 to enable all possible codec sample rates */  	snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); @@ -90,8 +87,8 @@ static int raumfeld_cs4270_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int fmt, clk = 0;  	int ret = 0; @@ -167,32 +164,14 @@ static int raumfeld_line_resume(struct platform_device *pdev)  	return 0;  } -static struct snd_soc_dai_link raumfeld_line_dai = { -	.name		= "CS4270", -	.stream_name	= "CS4270", -	.cpu_dai	= &pxa_ssp_dai[PXA_DAI_SSP1], -	.codec_dai	= &cs4270_dai, -	.ops		= &raumfeld_cs4270_ops, -}; - -static struct snd_soc_card snd_soc_line_raumfeld = { -	.name		= "Raumfeld analog", -	.platform	= &pxa2xx_soc_platform, -	.dai_link	= &raumfeld_line_dai, -	.suspend_post	= raumfeld_line_suspend, -	.resume_pre	= raumfeld_line_resume, -	.num_links	= 1, -}; - -  /* AK4104 */  static int raumfeld_ak4104_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int fmt, ret = 0, clk = 0;  	switch (params_rate(params)) { @@ -247,34 +226,35 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {  	.hw_params = raumfeld_ak4104_hw_params,  }; -static struct snd_soc_dai_link raumfeld_spdif_dai = { +static struct snd_soc_dai_link raumfeld_dai[] = { +{  	.name		= "ak4104",  	.stream_name	= "Playback", -	.cpu_dai	= &pxa_ssp_dai[PXA_DAI_SSP2], -	.codec_dai	= &ak4104_dai, +	.cpu_dai_name = "pxa-ssp-dai.1", +	.codec_dai_name = "ak4104-hifi", +	.platform_name = "pxa-pcm-audio",  	.ops		= &raumfeld_ak4104_ops, -}; - -static struct snd_soc_card snd_soc_spdif_raumfeld = { -	.name		= "Raumfeld S/PDIF", -	.platform	= &pxa2xx_soc_platform, -	.dai_link	= &raumfeld_spdif_dai, -	.num_links	= 1 -}; - -/* raumfeld_audio audio subsystem */ -static struct snd_soc_device raumfeld_line_devdata = { -	.card = &snd_soc_line_raumfeld, -	.codec_dev = &soc_codec_device_cs4270, -}; +	.codec_name = "ak4104-codec.0", +}, +{ +	.name		= "CS4270", +	.stream_name	= "CS4270", +	.cpu_dai_name = "pxa-ssp-dai.0", +	.platform_name = "pxa-pcm-audio", +	.codec_dai_name = "cs4270-hifi", +	.codec_name = "cs4270-codec.0-0048", +	.ops		= &raumfeld_cs4270_ops, +},}; -static struct snd_soc_device raumfeld_spdif_devdata = { -	.card = &snd_soc_spdif_raumfeld, -	.codec_dev = &soc_codec_device_ak4104, +static struct snd_soc_card snd_soc_raumfeld = { +	.name		= "Raumfeld", +	.dai_link	= raumfeld_dai, +	.suspend_post	= raumfeld_line_suspend, +	.resume_pre	= raumfeld_line_resume, +	.num_links	= ARRAY_SIZE(raumfeld_dai),  }; -static struct platform_device *raumfeld_audio_line_device; -static struct platform_device *raumfeld_audio_spdif_device; +static struct platform_device *raumfeld_audio_device;  static int __init raumfeld_audio_init(void)  { @@ -292,38 +272,19 @@ static int __init raumfeld_audio_init(void)  	set_max9485_clk(MAX9485_MCLK_FREQ_122880); -	/* LINE */ -	raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0); -	if (!raumfeld_audio_line_device) +	/* Register LINE and SPDIF */ +	raumfeld_audio_device = platform_device_alloc("soc-audio", 0); +	if (!raumfeld_audio_device)  		return -ENOMEM; -	platform_set_drvdata(raumfeld_audio_line_device, -			     &raumfeld_line_devdata); -	raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev; -	ret = platform_device_add(raumfeld_audio_line_device); -	if (ret) -		platform_device_put(raumfeld_audio_line_device); +	platform_set_drvdata(raumfeld_audio_device, +			     &snd_soc_raumfeld); +	ret = platform_device_add(raumfeld_audio_device);  	/* no S/PDIF on Speakers */  	if (machine_is_raumfeld_speaker())  		return ret; -	/* S/PDIF */ -	raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1); -	if (!raumfeld_audio_spdif_device) { -		platform_device_put(raumfeld_audio_line_device); -		return -ENOMEM; -	} - -	platform_set_drvdata(raumfeld_audio_spdif_device, -			     &raumfeld_spdif_devdata); -	raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev; -	ret = platform_device_add(raumfeld_audio_spdif_device); -	if (ret) { -		platform_device_put(raumfeld_audio_line_device); -		platform_device_put(raumfeld_audio_spdif_device); -	} -  	raumfeld_enable_audio(true);  	return ret; @@ -333,10 +294,7 @@ static void __exit raumfeld_audio_exit(void)  {  	raumfeld_enable_audio(false); -	platform_device_unregister(raumfeld_audio_line_device); - -	if (machine_is_raumfeld_connector()) -		platform_device_unregister(raumfeld_audio_spdif_device); +	platform_device_unregister(raumfeld_audio_device);  	i2c_unregister_device(max9486_client); diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a357e8c4..f470f360f4dd 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -28,7 +28,6 @@  #include <asm/mach-types.h>  #include <mach/spitz.h>  #include "../codecs/wm8750.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-i2s.h"  #define SPITZ_HP        0 @@ -107,7 +106,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec)  static int spitz_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->codec;  	/* check the jack status at stream startup */  	spitz_ext_control(codec); @@ -118,8 +117,8 @@ static int spitz_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0; @@ -274,8 +273,9 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = {  /*   * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device   */ -static int spitz_wm8750_init(struct snd_soc_codec *codec) +static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* NC codec pins */ @@ -308,8 +308,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link spitz_dai = {  	.name = "wm8750",  	.stream_name = "WM8750", -	.cpu_dai = &pxa_i2s_dai, -	.codec_dai = &wm8750_dai, +	.cpu_dai_name = "pxa-is2", +	.codec_dai_name = "wm8750-hifi", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm8750-codec.0-001a",  	.init = spitz_wm8750_init,  	.ops = &spitz_ops,  }; @@ -317,49 +319,10 @@ static struct snd_soc_dai_link spitz_dai = {  /* spitz audio machine driver */  static struct snd_soc_card snd_soc_spitz = {  	.name = "Spitz", -	.platform = &pxa2xx_soc_platform,  	.dai_link = &spitz_dai,  	.num_links = 1,  }; -/* spitz audio subsystem */ -static struct snd_soc_device spitz_snd_devdata = { -	.card = &snd_soc_spitz, -	.codec_dev = &soc_codec_dev_wm8750, -}; - -/* - * FIXME: This is a temporary bodge to avoid cross-tree merge issues. - * New drivers should register the wm8750 I2C device in the machine - * setup code (under arch/arm for ARM systems). - */ -static int wm8750_i2c_register(void) -{ -	struct i2c_board_info info; -	struct i2c_adapter *adapter; -	struct i2c_client *client; - -	memset(&info, 0, sizeof(struct i2c_board_info)); -	info.addr = 0x1b; -	strlcpy(info.type, "wm8750", I2C_NAME_SIZE); - -	adapter = i2c_get_adapter(0); -	if (!adapter) { -		printk(KERN_ERR "can't get i2c adapter 0\n"); -		return -ENODEV; -	} - -	client = i2c_new_device(adapter, &info); -	i2c_put_adapter(adapter); -	if (!client) { -		printk(KERN_ERR "can't add i2c device at 0x%x\n", -		(unsigned int)info.addr); -		return -ENODEV; -	} - -	return 0; -} -  static struct platform_device *spitz_snd_device;  static int __init spitz_init(void) @@ -369,16 +332,11 @@ static int __init spitz_init(void)  	if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))  		return -ENODEV; -	ret = wm8750_i2c_setup(); -	if (ret != 0) -		return ret; -  	spitz_snd_device = platform_device_alloc("soc-audio", -1);  	if (!spitz_snd_device)  		return -ENOMEM; -	platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata); -	spitz_snd_devdata.dev = &spitz_snd_device->dev; +	platform_set_drvdata(spitz_snd_device, &snd_soc_spitz);  	ret = platform_device_add(spitz_snd_device);  	if (ret) diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index dbbd3e9d1637..a3bfb2e8b70f 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -33,7 +33,6 @@  #include <mach/audio.h>  #include "../codecs/wm9712.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  static struct snd_soc_card tosa; @@ -80,7 +79,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec)  static int tosa_startup(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->socdev->card->codec; +	struct snd_soc_codec *codec = rtd->card->codec;  	/* check the jack status at stream startup */  	tosa_ext_control(codec); @@ -184,8 +183,9 @@ static const struct snd_kcontrol_new tosa_controls[] = {  		tosa_set_spk),  }; -static int tosa_ac97_init(struct snd_soc_codec *codec) +static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	snd_soc_dapm_nc_pin(codec, "OUT3"); @@ -212,16 +212,20 @@ static struct snd_soc_dai_link tosa_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], +	.cpu_dai_name = "pxa-ac97.0", +	.codec_dai_name = "wm9712-hifi", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm9712-codec",  	.init = tosa_ac97_init,  	.ops = &tosa_ops,  },  {  	.name = "AC97 Aux",  	.stream_name = "AC97 Aux", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -	.codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], +	.cpu_dai_name = "pxa-ac97.1", +	.codec_dai_name = "wm9712-aux", +	.platform_name = "pxa-pcm-audio", +	.codec_name = "wm9712-codec",  	.ops = &tosa_ops,  },  }; @@ -248,18 +252,12 @@ static int tosa_remove(struct platform_device *dev)  static struct snd_soc_card tosa = {  	.name = "Tosa", -	.platform = &pxa2xx_soc_platform,  	.dai_link = tosa_dai,  	.num_links = ARRAY_SIZE(tosa_dai),  	.probe = tosa_probe,  	.remove = tosa_remove,  }; -static struct snd_soc_device tosa_snd_devdata = { -	.card = &tosa, -	.codec_dev = &soc_codec_dev_wm9712, -}; -  static struct platform_device *tosa_snd_device;  static int __init tosa_init(void) @@ -275,8 +273,7 @@ static int __init tosa_init(void)  		goto err_alloc;  	} -	platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata); -	tosa_snd_devdata.dev = &tosa_snd_device->dev; +	platform_set_drvdata(tosa_snd_device, &tosa);  	ret = platform_device_add(tosa_snd_device);  	if (!ret) diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 4e4d2fa8ddc5..704f74b56ab6 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -30,7 +30,6 @@  #include <mach/z2.h>  #include "../codecs/wm8750.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-i2s.h"  static struct snd_soc_card snd_soc_z2; @@ -39,8 +38,8 @@ static int z2_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0; @@ -138,8 +137,9 @@ static const struct snd_soc_dapm_route audio_map[] = {  /*   * Logic for a wm8750 as connected on a Z2 Device   */ -static int z2_wm8750_init(struct snd_soc_codec *codec) +static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int ret;  	/* NC codec pins */ @@ -160,7 +160,7 @@ static int z2_wm8750_init(struct snd_soc_codec *codec)  		goto err;  	/* Jack detection API stuff */ -	ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET, +	ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,  				&hs_jack);  	if (ret)  		goto err; @@ -189,8 +189,10 @@ static struct snd_soc_ops z2_ops = {  static struct snd_soc_dai_link z2_dai = {  	.name		= "wm8750",  	.stream_name	= "WM8750", -	.cpu_dai	= &pxa_i2s_dai, -	.codec_dai	= &wm8750_dai, +	.cpu_dai_name	= "pxa-i2s", +	.codec_dai_name	= "wm8750-hifi", +	.platform_name = "pxa-pcm-audio", +	.codec_name	= "wm8750-codec.0-001a",  	.init		= z2_wm8750_init,  	.ops		= &z2_ops,  }; @@ -198,17 +200,10 @@ static struct snd_soc_dai_link z2_dai = {  /* z2 audio machine driver */  static struct snd_soc_card snd_soc_z2 = {  	.name		= "Z2", -	.platform	= &pxa2xx_soc_platform,  	.dai_link	= &z2_dai,  	.num_links	= 1,  }; -/* z2 audio subsystem */ -static struct snd_soc_device z2_snd_devdata = { -	.card		= &snd_soc_z2, -	.codec_dev	= &soc_codec_dev_wm8750, -}; -  static struct platform_device *z2_snd_device;  static int __init z2_init(void) @@ -222,8 +217,7 @@ static int __init z2_init(void)  	if (!z2_snd_device)  		return -ENOMEM; -	platform_set_drvdata(z2_snd_device, &z2_snd_devdata); -	z2_snd_devdata.dev = &z2_snd_device->dev; +	platform_set_drvdata(z2_snd_device, &snd_soc_z2);  	ret = platform_device_add(z2_snd_device);  	if (ret) diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index dd678ae24398..d27e05af7759 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -23,7 +23,6 @@  #include <sound/soc-dapm.h>  #include "../codecs/wm9713.h" -#include "pxa2xx-pcm.h"  #include "pxa2xx-ac97.h"  #include "pxa-ssp.h" @@ -71,10 +70,12 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{ "Multiactor", NULL, "SPKR" },  }; -static int zylonite_wm9713_init(struct snd_soc_codec *codec) +static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	if (clk_pout) -		snd_soc_dai_set_pll(&codec->dai[0], 0, 0, +		snd_soc_dai_set_pll(rtd->codec_dai, 0, 0,  				    clk_get_rate(pout), 0);  	snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, @@ -94,8 +95,8 @@ static int zylonite_voice_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int pll_out = 0;  	unsigned int wm9713_div = 0;  	int ret = 0; @@ -163,21 +164,27 @@ static struct snd_soc_dai_link zylonite_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], -	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], +	.codec_name = "wm9713-codec", +	.platform_name = "pxa-pcm-audio", +	.cpu_dai_name = "pxa-ac97.0", +	.codec_name = "wm9713-hifi",  	.init = zylonite_wm9713_init,  },  {  	.name = "AC97 Aux",  	.stream_name = "AC97 Aux", -	.cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], -	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], +	.codec_name = "wm9713-codec", +	.platform_name = "pxa-pcm-audio", +	.cpu_dai_name = "pxa-ac97.1", +	.codec_name = "wm9713-aux",  },  {  	.name = "WM9713 Voice",  	.stream_name = "WM9713 Voice", -	.cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3], -	.codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE], +	.codec_name = "wm9713-codec", +	.platform_name = "pxa-pcm-audio", +	.cpu_dai_name = "pxa-ssp-dai.2", +	.codec_name = "wm9713-voice",  	.ops = &zylonite_voice_ops,  },  }; @@ -248,14 +255,9 @@ static struct snd_soc_card zylonite = {  	.remove = &zylonite_remove,  	.suspend_post = &zylonite_suspend_post,  	.resume_pre = &zylonite_resume_pre, -	.platform = &pxa2xx_soc_platform,  	.dai_link = zylonite_dai,  	.num_links = ARRAY_SIZE(zylonite_dai), -}; - -static struct snd_soc_device zylonite_snd_ac97_devdata = { -	.card = &zylonite, -	.codec_dev = &soc_codec_dev_wm9713, +	.owner = THIS_MODULE,  };  static struct platform_device *zylonite_snd_ac97_device; @@ -268,9 +270,7 @@ static int __init zylonite_init(void)  	if (!zylonite_snd_ac97_device)  		return -ENOMEM; -	platform_set_drvdata(zylonite_snd_ac97_device, -			     &zylonite_snd_ac97_devdata); -	zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev; +	platform_set_drvdata(zylonite_snd_ac97_device, &zylonite);  	ret = platform_device_add(zylonite_snd_ac97_device);  	if (ret != 0) diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 213963ac3c28..1cdc37bd58f4 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -131,3 +131,21 @@ config SND_S3C64XX_SOC_SMARTQ  	depends on SND_S3C24XX_SOC && MACH_SMARTQ  	select SND_S3C64XX_SOC_I2S  	select SND_SOC_WM8750 + +config SND_S5PC110_SOC_AQUILA_WM8994 +	tristate "SoC I2S Audio support for AQUILA - WM8994" +	depends on SND_S3C24XX_SOC && MACH_AQUILA +	select SND_S3C64XX_SOC_I2S_V4 +	select SND_SOC_WM8994 +	help +	  Say Y if you want to add support for SoC audio on aquila +	  with the WM8994. + +config SND_S5PV210_SOC_GONI_WM8994 +	tristate "SoC I2S Audio support for GONI - WM8994" +	depends on SND_S3C24XX_SOC && MACH_GONI +	select SND_S3C64XX_SOC_I2S_V4 +	select SND_SOC_WM8994 +	help +	  Say Y if you want to add support for SoC audio on goni +	  with the WM8994. diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 50172c385d90..47ed6d70b90b 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -30,6 +30,8 @@ snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o  snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o  snd-soc-smdk-wm9713-objs := smdk_wm9713.o  snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o +snd-soc-aquila-wm8994-objs := aquila_wm8994.o +snd-soc-goni-wm8994-objs := goni_wm8994.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 @@ -43,3 +45,5 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv32  obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o  obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o  obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o +obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o +obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c new file mode 100644 index 000000000000..235d1973f7d0 --- /dev/null +++ b/sound/soc/s3c24xx/aquila_wm8994.c @@ -0,0 +1,295 @@ +/* + * aquila_wm8994.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Chanwoo Choi <cw00.choi@samsung.com> + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/jack.h> +#include <asm/mach-types.h> +#include <mach/gpio.h> +#include <mach/regs-clock.h> + +#include <linux/mfd/wm8994/core.h> +#include <linux/mfd/wm8994/registers.h> +#include "../codecs/wm8994.h" +#include "s3c-dma.h" +#include "s3c64xx-i2s.h" + +static struct snd_soc_card aquila; +static struct platform_device *aquila_snd_device; + +/* 3.5 pie jack */ +static struct snd_soc_jack jack; + +/* 3.5 pie jack detection DAPM pins */ +static struct snd_soc_jack_pin jack_pins[] = { +	{ +		.pin = "Headset Mic", +		.mask = SND_JACK_MICROPHONE, +	}, { +		.pin = "Headset Stereophone", +		.mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | +			SND_JACK_AVOUT, +	}, +}; + +/* 3.5 pie jack detection gpios */ +static struct snd_soc_jack_gpio jack_gpios[] = { +	{ +		.gpio = S5PV210_GPH0(6), +		.name = "DET_3.5", +		.report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | +			SND_JACK_AVOUT, +		.debounce_time = 200, +	}, +}; + +static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = { +	SND_SOC_DAPM_SPK("Ext Spk", NULL), +	SND_SOC_DAPM_SPK("Ext Rcv", NULL), +	SND_SOC_DAPM_HP("Headset Stereophone", NULL), +	SND_SOC_DAPM_MIC("Headset Mic", NULL), +	SND_SOC_DAPM_MIC("Main Mic", NULL), +	SND_SOC_DAPM_MIC("2nd Mic", NULL), +	SND_SOC_DAPM_LINE("Radio In", NULL), +}; + +static const struct snd_soc_dapm_route aquila_dapm_routes[] = { +	{"Ext Spk", NULL, "SPKOUTLP"}, +	{"Ext Spk", NULL, "SPKOUTLN"}, + +	{"Ext Rcv", NULL, "HPOUT2N"}, +	{"Ext Rcv", NULL, "HPOUT2P"}, + +	{"Headset Stereophone", NULL, "HPOUT1L"}, +	{"Headset Stereophone", NULL, "HPOUT1R"}, + +	{"IN1RN", NULL, "Headset Mic"}, +	{"IN1RP", NULL, "Headset Mic"}, + +	{"IN1RN", NULL, "2nd Mic"}, +	{"IN1RP", NULL, "2nd Mic"}, + +	{"IN1LN", NULL, "Main Mic"}, +	{"IN1LP", NULL, "Main Mic"}, + +	{"IN2LN", NULL, "Radio In"}, +	{"IN2RN", NULL, "Radio In"}, +}; + +static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ +	struct snd_soc_codec *codec = rtd->codec; +	int ret; + +	/* add aquila specific widgets */ +	snd_soc_dapm_new_controls(codec, aquila_dapm_widgets, +			ARRAY_SIZE(aquila_dapm_widgets)); + +	/* set up aquila specific audio routes */ +	snd_soc_dapm_add_routes(codec, aquila_dapm_routes, +			ARRAY_SIZE(aquila_dapm_routes)); + +	/* set endpoints to not connected */ +	snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); +	snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); +	snd_soc_dapm_nc_pin(codec, "SPKOUTRN"); +	snd_soc_dapm_nc_pin(codec, "SPKOUTRP"); + +	snd_soc_dapm_sync(codec); + +	/* Headset jack detection */ +	ret = snd_soc_jack_new(&aquila, "Headset Jack", +			SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, +			&jack); +	if (ret) +		return ret; + +	ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); +	if (ret) +		return ret; + +	ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); +	if (ret) +		return ret; + +	return 0; +} + +static int aquila_hifi_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->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	unsigned int pll_out = 24000000; +	int ret = 0; + +	/* set the cpu DAI configuration */ +	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | +			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the cpu system clock */ +	ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, +			0, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	/* set codec DAI configuration */ +	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | +			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the codec FLL */ +	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, +			params_rate(params) * 256); +	if (ret < 0) +		return ret; + +	/* set the codec system clock */ +	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, +			params_rate(params) * 256, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	return 0; +} + +static struct snd_soc_ops aquila_hifi_ops = { +	.hw_params = aquila_hifi_hw_params, +}; + +static int aquila_voice_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->codec_dai; +	unsigned int pll_out = 24000000; +	int ret = 0; + +	if (params_rate(params) != 8000) +		return -EINVAL; + +	/* set codec DAI configuration */ +	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | +			SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the codec FLL */ +	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, +			params_rate(params) * 256); +	if (ret < 0) +		return ret; + +	/* set the codec system clock */ +	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, +			params_rate(params) * 256, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	return 0; +} + +static struct snd_soc_dai_driver voice_dai = { +	.name = "aquila-voice-dai", +	.playback = { +		.channels_min = 1, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE,}, +	.capture = { +		.channels_min = 1, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE,}, +}; + +static struct snd_soc_ops aquila_voice_ops = { +	.hw_params = aquila_voice_hw_params, +}; + +static struct snd_soc_dai_link aquila_dai[] = { +{ +	.name = "WM8994", +	.stream_name = "WM8994 HiFi", +	.cpu_dai_name = "s3c64xx-i2s-v4", +	.codec_dai_name = "wm8994-hifi", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8994-codec.0-0x1a", +	.init = aquila_wm8994_init, +	.ops = &aquila_hifi_ops, +}, { +	.name = "WM8994 Voice", +	.stream_name = "Voice", +	.cpu_dai_name = "aquila-voice-dai", +	.codec_dai_name = "wm8994-voice", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8994-codec.0-0x1a", +	.ops = &aquila_voice_ops, +}, +}; + +static struct snd_soc_card aquila = { +	.name = "aquila", +	.dai_link = aquila_dai, +	.num_links = ARRAY_SIZE(aquila_dai), +}; + +static int __init aquila_init(void) +{ +	int ret; + +	if (!machine_is_aquila()) +		return -ENODEV; + +	aquila_snd_device = platform_device_alloc("soc-audio", -1); +	if (!aquila_snd_device) +		return -ENOMEM; + +	/* register voice DAI here */ +	ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai); +	if (ret) +		return ret; + +	platform_set_drvdata(aquila_snd_device, &aquila); +	ret = platform_device_add(aquila_snd_device); + +	if (ret) +		platform_device_put(aquila_snd_device); + +	return ret; +} + +static void __exit aquila_exit(void) +{ +	platform_device_unregister(aquila_snd_device); +} + +module_init(aquila_init); +module_exit(aquila_exit); + +/* Module information */ +MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)"); +MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c new file mode 100644 index 000000000000..694f702cc8e2 --- /dev/null +++ b/sound/soc/s3c24xx/goni_wm8994.c @@ -0,0 +1,298 @@ +/* + * goni_wm8994.c + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Chanwoo Choi <cw00.choi@samsung.com> + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/jack.h> +#include <asm/mach-types.h> +#include <mach/gpio.h> +#include <mach/regs-clock.h> + +#include <linux/mfd/wm8994/core.h> +#include <linux/mfd/wm8994/registers.h> +#include "../codecs/wm8994.h" +#include "s3c-dma.h" +#include "s3c64xx-i2s.h" + +static struct snd_soc_card goni; +static struct platform_device *goni_snd_device; + +/* 3.5 pie jack */ +static struct snd_soc_jack jack; + +/* 3.5 pie jack detection DAPM pins */ +static struct snd_soc_jack_pin jack_pins[] = { +	{ +		.pin = "Headset Mic", +		.mask = SND_JACK_MICROPHONE, +	}, { +		.pin = "Headset Stereophone", +		.mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | +			SND_JACK_AVOUT, +	}, +}; + +/* 3.5 pie jack detection gpios */ +static struct snd_soc_jack_gpio jack_gpios[] = { +	{ +		.gpio = S5PV210_GPH0(6), +		.name = "DET_3.5", +		.report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | +			SND_JACK_AVOUT, +		.debounce_time = 200, +	}, +}; + +static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { +	SND_SOC_DAPM_SPK("Ext Left Spk", NULL), +	SND_SOC_DAPM_SPK("Ext Right Spk", NULL), +	SND_SOC_DAPM_SPK("Ext Rcv", NULL), +	SND_SOC_DAPM_HP("Headset Stereophone", NULL), +	SND_SOC_DAPM_MIC("Headset Mic", NULL), +	SND_SOC_DAPM_MIC("Main Mic", NULL), +	SND_SOC_DAPM_MIC("2nd Mic", NULL), +	SND_SOC_DAPM_LINE("Radio In", NULL), +}; + +static const struct snd_soc_dapm_route goni_dapm_routes[] = { +	{"Ext Left Spk", NULL, "SPKOUTLP"}, +	{"Ext Left Spk", NULL, "SPKOUTLN"}, + +	{"Ext Right Spk", NULL, "SPKOUTRP"}, +	{"Ext Right Spk", NULL, "SPKOUTRN"}, + +	{"Ext Rcv", NULL, "HPOUT2N"}, +	{"Ext Rcv", NULL, "HPOUT2P"}, + +	{"Headset Stereophone", NULL, "HPOUT1L"}, +	{"Headset Stereophone", NULL, "HPOUT1R"}, + +	{"IN1RN", NULL, "Headset Mic"}, +	{"IN1RP", NULL, "Headset Mic"}, + +	{"IN1RN", NULL, "2nd Mic"}, +	{"IN1RP", NULL, "2nd Mic"}, + +	{"IN1LN", NULL, "Main Mic"}, +	{"IN1LP", NULL, "Main Mic"}, + +	{"IN2LN", NULL, "Radio In"}, +	{"IN2RN", NULL, "Radio In"}, +}; + +static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ +	struct snd_soc_codec *codec = rtd->codec; +	int ret; + +	/* add goni specific widgets */ +	snd_soc_dapm_new_controls(codec, goni_dapm_widgets, +			ARRAY_SIZE(goni_dapm_widgets)); + +	/* set up goni specific audio routes */ +	snd_soc_dapm_add_routes(codec, goni_dapm_routes, +			ARRAY_SIZE(goni_dapm_routes)); + +	/* set endpoints to not connected */ +	snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); +	snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); +	snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); + +	snd_soc_dapm_sync(codec); + +	/* Headset jack detection */ +	ret = snd_soc_jack_new(&goni, "Headset Jack", +			SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, +			&jack); +	if (ret) +		return ret; + +	ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); +	if (ret) +		return ret; + +	ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); +	if (ret) +		return ret; + +	return 0; +} + +static int goni_hifi_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->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	unsigned int pll_out = 24000000; +	int ret = 0; + +	/* set the cpu DAI configuration */ +	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | +			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the cpu system clock */ +	ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, +			0, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	/* set codec DAI configuration */ +	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | +			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the codec FLL */ +	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, +			params_rate(params) * 256); +	if (ret < 0) +		return ret; + +	/* set the codec system clock */ +	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, +			params_rate(params) * 256, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	return 0; +} + +static struct snd_soc_ops goni_hifi_ops = { +	.hw_params = goni_hifi_hw_params, +}; + +static int goni_voice_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->codec_dai; +	unsigned int pll_out = 24000000; +	int ret = 0; + +	if (params_rate(params) != 8000) +		return -EINVAL; + +	/* set codec DAI configuration */ +	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | +			SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); +	if (ret < 0) +		return ret; + +	/* set the codec FLL */ +	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, +			params_rate(params) * 256); +	if (ret < 0) +		return ret; + +	/* set the codec system clock */ +	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, +			params_rate(params) * 256, SND_SOC_CLOCK_IN); +	if (ret < 0) +		return ret; + +	return 0; +} + +static struct snd_soc_dai_driver voice_dai = { +	.name = "goni-voice-dai", +	.id = 0, +	.playback = { +		.channels_min = 1, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE,}, +	.capture = { +		.channels_min = 1, +		.channels_max = 2, +		.rates = SNDRV_PCM_RATE_8000, +		.formats = SNDRV_PCM_FMTBIT_S16_LE,}, +}; + +static struct snd_soc_ops goni_voice_ops = { +	.hw_params = goni_voice_hw_params, +}; + +static struct snd_soc_dai_link goni_dai[] = { +{ +	.name = "WM8994", +	.stream_name = "WM8994 HiFi", +	.cpu_dai_name = "s3c64xx-i2s-v4", +	.codec_dai_name = "wm8994-hifi", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8994-codec.0-0x1a", +	.init = goni_wm8994_init, +	.ops = &goni_hifi_ops, +}, { +	.name = "WM8994 Voice", +	.stream_name = "Voice", +	.cpu_dai_name = "goni-voice-dai", +	.codec_dai_name = "wm8994-voice", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8994-codec.0-0x1a", +	.ops = &goni_voice_ops, +}, +}; + +static struct snd_soc_card goni = { +	.name = "goni", +	.dai_link = goni_dai, +	.num_links = ARRAY_SIZE(goni_dai), +}; + +static int __init goni_init(void) +{ +	int ret; + +	if (!machine_is_goni()) +		return -ENODEV; + +	goni_snd_device = platform_device_alloc("soc-audio", -1); +	if (!goni_snd_device) +		return -ENOMEM; + +	/* register voice DAI here */ +	ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); +	if (ret) +		return ret; + +	platform_set_drvdata(goni_snd_device, &goni); +	ret = platform_device_add(goni_snd_device); + +	if (ret) +		platform_device_put(goni_snd_device); + +	return ret; +} + +static void __exit goni_exit(void) +{ +	platform_device_unregister(goni_snd_device); +} + +module_init(goni_init); +module_exit(goni_exit); + +/* Module information */ +MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); +MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c index 8c108b121c10..49605cd83947 100644 --- a/sound/soc/s3c24xx/jive_wm8750.c +++ b/sound/soc/s3c24xx/jive_wm8750.c @@ -49,8 +49,8 @@ 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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	struct s3c_i2sv2_rate_calc div;  	unsigned int clk = 0;  	int ret = 0; @@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = {  	.hw_params	= jive_hw_params,  }; -static int jive_wm8750_init(struct snd_soc_codec *codec) +static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* These endpoints are not being used. */ @@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link jive_dai = {  	.name		= "wm8750",  	.stream_name	= "WM8750", -	.cpu_dai	= &s3c2412_i2s_dai, -	.codec_dai	= &wm8750_dai, +	.cpu_dai_name	= "s3c2412-i2s", +	.codec_dai_name = "wm8750-hifi", +	.platform_name	= "s3c24xx-pcm-audio", +	.codec_name	= "wm8750-codec.0-0x1a",  	.init		= jive_wm8750_init,  	.ops		= &jive_ops,  }; @@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = {  /* jive audio machine driver */  static struct snd_soc_card snd_soc_machine_jive = {  	.name		= "Jive", -	.platform	= &s3c24xx_soc_platform,  	.dai_link	= &jive_dai,  	.num_links	= 1,  }; -/* jive audio subsystem */ -static struct snd_soc_device jive_snd_devdata = { -	.card		= &snd_soc_machine_jive, -	.codec_dev	= &soc_codec_dev_wm8750, -}; -  static struct platform_device *jive_snd_device;  static int __init jive_init(void) @@ -173,8 +169,7 @@ static int __init jive_init(void)  	if (!jive_snd_device)  		return -ENOMEM; -	platform_set_drvdata(jive_snd_device, &jive_snd_devdata); -	jive_snd_devdata.dev = &jive_snd_device->dev; +	platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive);  	ret = platform_device_add(jive_snd_device);  	if (ret) diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c index ffa954fe6931..abe64abe8c84 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c @@ -23,7 +23,6 @@  #include <sound/soc.h>  #include <sound/soc-dapm.h> -#include "../codecs/ac97.h"  #include "s3c-dma.h"  #include "s3c-ac97.h" @@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], -	.codec_dai = &ac97_dai, +	.cpu_dai_name = "s3c-ac97", +	.codec_dai_name = "ac97-hifi", +	.codec_name = "ac97-codec", +	.platform_name = "s3c24xx-pcm-audio",  },  };  static struct snd_soc_card ln2440sbc = {  	.name = "LN2440SBC", -	.platform = &s3c24xx_soc_platform,  	.dai_link = ln2440sbc_dai,  	.num_links = ARRAY_SIZE(ln2440sbc_dai),  }; -static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { -	.card = &ln2440sbc, -	.codec_dev = &soc_codec_dev_ac97, -}; -  static struct platform_device *ln2440sbc_snd_ac97_device;  static int __init ln2440sbc_init(void) @@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void)  	if (!ln2440sbc_snd_ac97_device)  		return -ENOMEM; -	platform_set_drvdata(ln2440sbc_snd_ac97_device, -				&ln2440sbc_snd_ac97_devdata); -	ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev; +	platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc);  	ret = platform_device_add(ln2440sbc_snd_ac97_device);  	if (ret) diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c index 209c25994c7e..c457bfd8297c 100644 --- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c @@ -41,8 +41,8 @@ static int neo1973_gta02_hifi_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int pll_out = 0, bclk = 0;  	int ret = 0;  	unsigned long iis_clkrate; @@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,  static int neo1973_gta02_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; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	/* disable the PLL */  	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); @@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params(  	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 *codec_dai = rtd->codec_dai;  	unsigned int pcmdiv = 0;  	int ret = 0;  	unsigned long iis_clkrate; @@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params(  static int neo1973_gta02_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; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	/* disable the PLL */  	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); @@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w,  			struct snd_kcontrol *k,  			int event)  { -	gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); +	gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));  	return 0;  } @@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {   * This is an example machine initialisation for a wm8753 connected to a   * neo1973 GTA02.   */ -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) +static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	/* set up NC codec pins */ @@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)  /*   * BT Codec DAI   */ -static struct snd_soc_dai bt_dai = { -	.name = "Bluetooth", -	.id = 0, +static struct snd_soc_dai_driver bt_dai = { +	.name = "bluetooth-dai",  	.playback = {  		.channels_min = 1,  		.channels_max = 1, @@ -397,32 +397,30 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = {  { /* Hifi Playback - for similatious use with voice below */  	.name = "WM8753",  	.stream_name = "WM8753 HiFi", -	.cpu_dai = &s3c24xx_i2s_dai, -	.codec_dai = &wm8753_dai[WM8753_DAI_HIFI], +	.cpu_dai_name = "s3c24xx-i2s", +	.codec_dai_name = "wm8753-hifi",  	.init = neo1973_gta02_wm8753_init, +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8753-codec.0-0x1a",  	.ops = &neo1973_gta02_hifi_ops,  },  { /* Voice via BT */  	.name = "Bluetooth",  	.stream_name = "Voice", -	.cpu_dai = &bt_dai, -	.codec_dai = &wm8753_dai[WM8753_DAI_VOICE], +	.cpu_dai_name = "bluetooth-dai", +	.codec_dai_name = "wm8753-voice",  	.ops = &neo1973_gta02_voice_ops, +	.codec_name = "wm8753-codec.0-0x1a", +	.platform_name = "s3c24xx-pcm-audio",  },  };  static struct snd_soc_card neo1973_gta02 = {  	.name = "neo1973-gta02", -	.platform = &s3c24xx_soc_platform,  	.dai_link = neo1973_gta02_dai,  	.num_links = ARRAY_SIZE(neo1973_gta02_dai),  }; -static struct snd_soc_device neo1973_gta02_snd_devdata = { -	.card = &neo1973_gta02, -	.codec_dev = &soc_codec_dev_wm8753, -}; -  static struct platform_device *neo1973_gta02_snd_device;  static int __init neo1973_gta02_init(void) @@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void)  		return -ENODEV;  	} -	/* register bluetooth DAI here */ -	ret = snd_soc_register_dai(&bt_dai); -	if (ret) -		return ret; -  	neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);  	if (!neo1973_gta02_snd_device)  		return -ENOMEM; -	platform_set_drvdata(neo1973_gta02_snd_device, -			&neo1973_gta02_snd_devdata); -	neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; +	/* register bluetooth DAI here */ +	ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai); +	if (ret) { +		platform_device_put(neo1973_gta02_snd_device); +		return ret; +	} + +	platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);  	ret = platform_device_add(neo1973_gta02_snd_device);  	if (ret) { @@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void)  		goto err_unregister_device;  	} -	ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); +	ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1);  	if (ret) {  		pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);  		goto err_free_gpio_hp_in; @@ -493,7 +491,7 @@ module_init(neo1973_gta02_init);  static void __exit neo1973_gta02_exit(void)  { -	snd_soc_unregister_dai(&bt_dai); +	snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1);  	platform_device_unregister(neo1973_gta02_snd_device);  	gpio_free(GTA02_GPIO_HP_IN);  	gpio_free(GTA02_GPIO_AMP_SHUT); diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 0cb4f86f6d1e..d7a39a0fe99b 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c @@ -57,8 +57,8 @@ static int neo1973_hifi_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int pll_out = 0, bclk = 0;  	int ret = 0;  	unsigned long iis_clkrate; @@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,  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; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	pr_debug("Entered %s\n", __func__); @@ -167,7 +167,7 @@ static int neo1973_voice_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 *codec_dai = rtd->codec_dai;  	unsigned int pcmdiv = 0;  	int ret = 0;  	unsigned long iis_clkrate; @@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,  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; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	pr_debug("Entered %s\n", __func__); @@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {   * neo1973 II. It is missing logic to detect hp/mic insertions and logic   * to re-route the audio in such an event.   */ -static int neo1973_wm8753_init(struct snd_soc_codec *codec) +static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec;  	int err;  	pr_debug("Entered %s\n", __func__); @@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)   * BT Codec DAI   */  static struct snd_soc_dai bt_dai = { -	.name = "Bluetooth", -	.id = 0, +	.name = "bluetooth-dai",  	.playback = {  		.channels_min = 1,  		.channels_max = 1, @@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_dai[] = {  { /* Hifi Playback - for similatious use with voice below */  	.name = "WM8753",  	.stream_name = "WM8753 HiFi", -	.cpu_dai = &s3c24xx_i2s_dai, -	.codec_dai = &wm8753_dai[WM8753_DAI_HIFI], +	.platform_name = "s3c24xx-pcm-audio", +	.cpu_dai_name = "s3c24xx-i2s", +	.codec_dai_name = "wm8753-hifi", +	.codec_name = "wm8753-codec.0-0x1a",  	.init = neo1973_wm8753_init,  	.ops = &neo1973_hifi_ops,  },  { /* Voice via BT */  	.name = "Bluetooth",  	.stream_name = "Voice", -	.cpu_dai = &bt_dai, -	.codec_dai = &wm8753_dai[WM8753_DAI_VOICE], +	.platform_name = "s3c24xx-pcm-audio", +	.cpu_dai_name = "bluetooth-dai", +	.codec_dai_name = "wm8753-voice", +	.codec_name = "wm8753-codec.0-0x1a",  	.ops = &neo1973_voice_ops,  },  };  static struct snd_soc_card neo1973 = {  	.name = "neo1973", -	.platform = &s3c24xx_soc_platform,  	.dai_link = neo1973_dai,  	.num_links = ARRAY_SIZE(neo1973_dai),  }; -static struct snd_soc_device neo1973_snd_devdata = { -	.card = &neo1973, -	.codec_dev = &soc_codec_dev_wm8753, -}; -  static int lm4857_i2c_probe(struct i2c_client *client,  			    const struct i2c_device_id *id)  { @@ -673,8 +671,7 @@ static int __init neo1973_init(void)  	if (!neo1973_snd_device)  		return -ENOMEM; -	platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); -	neo1973_snd_devdata.dev = &neo1973_snd_device->dev; +	platform_set_drvdata(neo1973_snd_device, &neo1973);  	ret = platform_device_add(neo1973_snd_device);  	if (ret) { diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index 31f6d45b6384..26f4ed90a0ee 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c @@ -222,7 +222,7 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,  				  struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	struct s3c_dma_params *dma_data;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -241,7 +241,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,  	u32 ac_glbctrl;  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct s3c_dma_params *dma_data = -		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);  	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) @@ -277,7 +277,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,  				      struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)  		return -ENODEV; @@ -293,7 +293,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,  	u32 ac_glbctrl;  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct s3c_dma_params *dma_data = -		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);  	ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; @@ -328,10 +328,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {  	.trigger	= s3c_ac97_mic_trigger,  }; -struct snd_soc_dai s3c_ac97_dai[] = { +static struct snd_soc_dai_driver s3c_ac97_dai[] = {  	[S3C_AC97_DAI_PCM] = {  		.name =	"s3c-ac97", -		.id = S3C_AC97_DAI_PCM,  		.ac97_control = 1,  		.playback = {  			.stream_name = "AC97 Playback", @@ -349,7 +348,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {  	},  	[S3C_AC97_DAI_MIC] = {  		.name = "s3c-ac97-mic", -		.id = S3C_AC97_DAI_MIC,  		.ac97_control = 1,  		.capture = {  			.stream_name = "AC97 Mic Capture", @@ -360,7 +358,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {  		.ops = &s3c_ac97_mic_dai_ops,  	},  }; -EXPORT_SYMBOL_GPL(s3c_ac97_dai);  static __devinit int s3c_ac97_probe(struct platform_device *pdev)  { @@ -449,10 +446,8 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)  		goto err4;  	} -	s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev; -	s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev; - -	ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); +	ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai, +			ARRAY_SIZE(s3c_ac97_dai));  	if (ret)  		goto err5; @@ -476,7 +471,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)  {  	struct resource *mem_res, *irq_res; -	snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));  	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  	if (irq_res) @@ -518,3 +513,4 @@ module_exit(s3c_ac97_exit);  MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");  MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c-ac97"); diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h index 278198379def..5dcedd07fdbb 100644 --- a/sound/soc/s3c24xx/s3c-ac97.h +++ b/sound/soc/s3c24xx/s3c-ac97.h @@ -18,6 +18,4 @@  #define S3C_AC97_DAI_PCM 0  #define S3C_AC97_DAI_MIC 1 -extern struct snd_soc_dai s3c_ac97_dai[]; -  #endif /* __S3C_AC97_H_ */ diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 1b61c23ff300..54bff83c98b4 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c @@ -147,7 +147,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	unsigned long totbytes = params_buffer_bytes(params);  	struct s3c_dma_params *dma = -		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	int ret = 0; @@ -441,14 +441,14 @@ static int s3c_dma_new(struct snd_card *card,  	if (!card->dev->coherent_dma_mask)  		card->dev->coherent_dma_mask = 0xffffffff; -	if (dai->playback.channels_min) { +	if (dai->driver->playback.channels_min) {  		ret = s3c_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_PLAYBACK);  		if (ret)  			goto out;  	} -	if (dai->capture.channels_min) { +	if (dai->driver->capture.channels_min) {  		ret = s3c_preallocate_dma_buffer(pcm,  			SNDRV_PCM_STREAM_CAPTURE);  		if (ret) @@ -458,26 +458,46 @@ static int s3c_dma_new(struct snd_card *card,  	return ret;  } -struct snd_soc_platform s3c24xx_soc_platform = { -	.name		= "s3c24xx-audio", -	.pcm_ops 	= &s3c_dma_ops, +static struct snd_soc_platform_driver s3c24xx_soc_platform = { +	.ops		= &s3c_dma_ops,  	.pcm_new	= s3c_dma_new,  	.pcm_free	= s3c_dma_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); -static int __init s3c24xx_soc_platform_init(void) +static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&s3c24xx_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform);  } -module_init(s3c24xx_soc_platform_init); -static void __exit s3c24xx_soc_platform_exit(void) +static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&s3c24xx_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver s3c24xx_pcm_driver = { +	.driver = { +		.name = "s3c24xx-pcm-audio", +		.owner = THIS_MODULE, +	}, + +	.probe = s3c24xx_soc_platform_probe, +	.remove = __devexit_p(s3c24xx_soc_platform_remove), +}; + +static int __init snd_s3c24xx_pcm_init(void) +{ +	return platform_driver_register(&s3c24xx_pcm_driver); +} +module_init(snd_s3c24xx_pcm_init); + +static void __exit snd_s3c24xx_pcm_exit(void) +{ +	platform_driver_unregister(&s3c24xx_pcm_driver);  } -module_exit(s3c24xx_soc_platform_exit); +module_exit(snd_s3c24xx_pcm_exit);  MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");  MODULE_DESCRIPTION("Samsung S3C Audio DMA module");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c24xx-pcm-audio"); diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h index 69bb6bf6fc1c..748c07d7c075 100644 --- a/sound/soc/s3c24xx/s3c-dma.h +++ b/sound/soc/s3c24xx/s3c-dma.h @@ -25,7 +25,6 @@ struct s3c_dma_params {  #define S3C24XX_DAI_I2S			0  /* platform data */ -extern struct snd_soc_platform s3c24xx_soc_platform;  extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;  #endif diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 64376b2aac73..b3866d5b19e9 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -49,7 +49,7 @@  static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)  { -	return cpu_dai->private_data; +	return snd_soc_dai_get_drvdata(cpu_dai);  }  #define bit_set(v, b) (((v) & (b)) ? 1 : 0) @@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,  static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params, -				 struct snd_soc_dai *socdai) +				 struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai_link *dai = rtd->dai; -	struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); +	struct s3c_i2sv2_info *i2s = to_info(dai);  	struct s3c_dma_params *dma_data;  	u32 iismod; @@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,  	else  		dma_data = i2s->dma_capture; -	snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); +	snd_soc_dai_set_dma_data(dai, substream, dma_data);  	/* Working copies of register */  	iismod = readl(i2s->regs + S3C2412_IISMOD); @@ -396,12 +394,12 @@ 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); +	struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai);  	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);  	unsigned long irqs;  	int ret = 0;  	struct s3c_dma_params *dma_data = -		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);  	pr_debug("Entered %s\n", __func__); @@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,  }  EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); -int s3c_i2sv2_probe(struct platform_device *pdev, -		    struct snd_soc_dai *dai, +int s3c_i2sv2_probe(struct snd_soc_dai *dai,  		    struct s3c_i2sv2_info *i2s,  		    unsigned long base)  { -	struct device *dev = &pdev->dev; +	struct device *dev = dai->dev;  	unsigned int iismod;  	i2s->dev = dev;  	/* record our i2s structure for later use in the callbacks */ -	dai->private_data = i2s; - -	if (!base) { -		struct resource *res = platform_get_resource(pdev, -							     IORESOURCE_MEM, -							     0); -		if (!res) { -			dev_err(dev, "Unable to get register resource\n"); -			return -ENXIO; -		} - -		if (!request_mem_region(res->start, resource_size(res), -					"s3c64xx-i2s-v4")) { -			dev_err(dev, "Unable to request register region\n"); -			return -EBUSY; -		} - -		base = res->start; -	} +	snd_soc_dai_set_drvdata(dai, i2s);  	i2s->regs = ioremap(base, 0x100);  	if (i2s->regs == NULL) { @@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)  #define s3c2412_i2s_resume  NULL  #endif -int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) +int s3c_i2sv2_register_dai(struct device *dev, int id, +		struct snd_soc_dai_driver *drv)  { -	struct snd_soc_dai_ops *ops = dai->ops; +	struct snd_soc_dai_ops *ops = drv->ops;  	ops->trigger = s3c2412_i2s_trigger;  	if (!ops->hw_params) @@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)  	if (!ops->delay)  		ops->delay = s3c2412_i2s_delay; -	dai->suspend = s3c2412_i2s_suspend; -	dai->resume = s3c2412_i2s_resume; +	drv->suspend = s3c2412_i2s_suspend; +	drv->resume = s3c2412_i2s_resume; -	return snd_soc_register_dai(dai); +	return snd_soc_register_dai(dev, drv);  }  EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index 766f43a13d8b..d45830151484 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h @@ -66,6 +66,8 @@ struct s3c_i2sv2_info {  	u32		 suspend_iismod;  	u32		 suspend_iiscon;  	u32		 suspend_iispsr; + +	unsigned long	base;  };  extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); @@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,  /**   * 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, +extern int s3c_i2sv2_probe(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 + * @dev: DAI device + * @id: DAI ID + * @drv: The driver 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); +extern int s3c_i2sv2_register_dai(struct device *dev, int id, +		struct snd_soc_dai_driver *drv);  #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index 326f0a9e7e30..6174e26e433e 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c @@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = {  static struct s3c_pcm_info s3c_pcm[2]; -static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai) -{ -	return cpu_dai->private_data; -} -  static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)  {  	void __iomem *regs = pcm->regs; @@ -132,7 +127,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,  			       struct snd_soc_dai *dai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai); +	struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	unsigned long flags;  	dev_dbg(pcm->dev, "Entered %s\n", __func__); @@ -176,8 +171,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,  				 struct snd_soc_dai *socdai)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai_link *dai = rtd->dai; -	struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); +	struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	struct s3c_dma_params *dma_data;  	void __iomem *regs = pcm->regs;  	struct clk *clk; @@ -192,7 +186,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,  	else  		dma_data = pcm->dma_capture; -	snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); +	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);  	/* Strictly check for sample size */  	switch (params_format(params)) { @@ -242,7 +236,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,  static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,  			       unsigned int fmt)  { -	struct s3c_pcm_info *pcm = to_info(cpu_dai); +	struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);  	void __iomem *regs = pcm->regs;  	unsigned long flags;  	int ret = 0; @@ -313,7 +307,7 @@ exit:  static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,  						int div_id, int div)  { -	struct s3c_pcm_info *pcm = to_info(cpu_dai); +	struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);  	switch (div_id) {  	case S3C_PCM_SCLK_PER_FS: @@ -330,7 +324,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,  static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,  				  int clk_id, unsigned int freq, int dir)  { -	struct s3c_pcm_info *pcm = to_info(cpu_dai); +	struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);  	void __iomem *regs = pcm->regs;  	u32 clkctl = readl(regs + S3C_PCM_CLKCTL); @@ -366,10 +360,9 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {  #define S3C_PCM_RATES  SNDRV_PCM_RATE_8000_96000 -#define S3C_PCM_DECLARE(n)			\ +#define S3C_PCM_DAI_DECLARE			\  {								\ -	.name		 = "samsung-pcm",			\ -	.id		 = (n),				\ +	.name		 = "samsung-dai",			\  	.symmetric_rates = 1,					\  	.ops = &s3c_pcm_dai_ops,				\  	.playback = {						\ @@ -386,16 +379,15 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {  	},							\  } -struct snd_soc_dai s3c_pcm_dai[] = { -	S3C_PCM_DECLARE(0), -	S3C_PCM_DECLARE(1), +struct snd_soc_dai_driver s3c_pcm_dai[] = { +	S3C_PCM_DAI_DECLARE, +	S3C_PCM_DAI_DECLARE,  };  EXPORT_SYMBOL_GPL(s3c_pcm_dai);  static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)  {  	struct s3c_pcm_info *pcm; -	struct snd_soc_dai *dai;  	struct resource *mem_res, *dmatx_res, *dmarx_res;  	struct s3c_audio_pdata *pcm_pdata;  	int ret; @@ -437,9 +429,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)  	spin_lock_init(&pcm->lock); -	dai = &s3c_pcm_dai[pdev->id]; -	dai->dev = &pdev->dev; -  	/* Default is 128fs */  	pcm->sclk_per_fs = 128; @@ -452,7 +441,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)  	clk_enable(pcm->cclk);  	/* record our pcm structure for later use in the callbacks */ -	dai->private_data = pcm; +	dev_set_drvdata(&pdev->dev, pcm);  	if (!request_mem_region(mem_res->start,  				resource_size(mem_res), "samsung-pcm")) { @@ -476,7 +465,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)  	}  	clk_enable(pcm->pclk); -	ret = snd_soc_register_dai(dai); +	ret = snd_soc_register_dai(&pdev->dev, s3c_pcm_dai);  	if (ret != 0) {  		dev_err(&pdev->dev, "failed to get pcm_clock\n");  		goto err5; @@ -514,6 +503,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)  	struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];  	struct resource *mem_res; +	snd_soc_unregister_dai(&pdev->dev); +  	iounmap(pcm->regs);  	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -531,7 +522,7 @@ static struct platform_driver s3c_pcm_driver = {  	.probe  = s3c_pcm_dev_probe,  	.remove = s3c_pcm_dev_remove,  	.driver = { -		.name = "samsung-pcm", +		.name = "samsung-pcm-audio",  		.owner = THIS_MODULE,  	},  }; @@ -552,3 +543,4 @@ module_exit(s3c_pcm_exit);  MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");  MODULE_DESCRIPTION("S3C PCM Controller Driver");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-pcm-audio"); diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index 709adef9d043..4a861cfa52c5 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c @@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {  static struct s3c_i2sv2_info s3c2412_i2s; -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) -{ -	return cpu_dai->private_data; -} - -static int s3c2412_i2s_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int s3c2412_i2s_probe(struct snd_soc_dai *dai)  {  	int ret;  	pr_debug("Entered %s\n", __func__); -	ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); +	ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);  	if (ret)  		return ret;  	s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;  	s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; -	s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); +	s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");  	if (s3c2412_i2s.iis_cclk == NULL) {  		pr_err("failed to get i2sclk clock\n");  		iounmap(s3c2412_i2s.regs); @@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,  	return 0;  } +static int s3c2412_i2s_remove(struct snd_soc_dai *dai) +{ +	clk_disable(s3c2412_i2s.iis_cclk); +	clk_put(s3c2412_i2s.iis_cclk); +	iounmap(s3c2412_i2s.regs); + +	return 0; +} +  static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *cpu_dai)  { -	struct s3c_i2sv2_info *i2s = to_info(cpu_dai); +	struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);  	struct s3c_dma_params *dma_data;  	u32 iismod; @@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {  	.hw_params	= s3c2412_i2s_hw_params,  }; -struct snd_soc_dai s3c2412_i2s_dai = { -	.name		= "s3c2412-i2s", -	.id		= 0, +static struct snd_soc_dai_driver s3c2412_i2s_dai = {  	.probe		= s3c2412_i2s_probe, +	.remove	= s3c2412_i2s_remove,  	.playback = {  		.channels_min	= 2,  		.channels_max	= 2, @@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = {  	},  	.ops = &s3c2412_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); + +static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai); +} + +static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver s3c2412_iis_driver = { +	.probe  = s3c2412_iis_dev_probe, +	.remove = s3c2412_iis_dev_remove, +	.driver = { +		.name = "s3c2412-iis", +		.owner = THIS_MODULE, +	}, +};  static int __init s3c2412_i2s_init(void)  { -	return  s3c_i2sv2_register_dai(&s3c2412_i2s_dai); +	return platform_driver_register(&s3c2412_iis_driver);  }  module_init(s3c2412_i2s_init);  static void __exit s3c2412_i2s_exit(void)  { -	snd_soc_unregister_dai(&s3c2412_i2s_dai); +	platform_driver_unregister(&s3c2412_iis_driver);  }  module_exit(s3c2412_i2s_exit); @@ -188,3 +209,4 @@ module_exit(s3c2412_i2s_exit);  MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");  MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c2412-iis"); diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 0b5686b4d5c3..01a0471ac65c 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h @@ -24,6 +24,4 @@  #define S3C2412_CLKSRC_PCLK	S3C_I2SV2_CLKSRC_PCLK  #define S3C2412_CLKSRC_I2SCLK	S3C_I2SV2_CLKSRC_AUDIOBUS -extern struct snd_soc_dai s3c2412_i2s_dai; -  #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index c3ac890a3986..e060daaa458f 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,  	else  		dma_data = &s3c24xx_i2s_pcm_stereo_in; -	snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); +	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);  	/* Working copies of register */  	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -280,9 +280,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,  			       struct snd_soc_dai *dai)  {  	int ret = 0; -	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct s3c_dma_params *dma_data = -		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(dai, substream);  	pr_debug("Entered %s\n", __func__); @@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void)  }  EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); -static int s3c24xx_i2s_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)  {  	pr_debug("Entered %s\n", __func__); @@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,  	if (s3c24xx_i2s.regs == NULL)  		return -ENXIO; -	s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); +	s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");  	if (s3c24xx_i2s.iis_clk == NULL) {  		pr_err("failed to get iis_clock\n");  		iounmap(s3c24xx_i2s.regs); @@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {  	.set_sysclk	= s3c24xx_i2s_set_sysclk,  }; -struct snd_soc_dai s3c24xx_i2s_dai = { -	.name = "s3c24xx-i2s", -	.id = 0, +static struct snd_soc_dai_driver s3c24xx_i2s_dai = {  	.probe = s3c24xx_i2s_probe,  	.suspend = s3c24xx_i2s_suspend,  	.resume = s3c24xx_i2s_resume, @@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = {  		.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},  	.ops = &s3c24xx_i2s_dai_ops,  }; -EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); + +static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); +} + +static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev); +	return 0; +} + +static struct platform_driver s3c24xx_iis_driver = { +	.probe  = s3c24xx_iis_dev_probe, +	.remove = s3c24xx_iis_dev_remove, +	.driver = { +		.name = "s3c24xx-iis", +		.owner = THIS_MODULE, +	}, +};  static int __init s3c24xx_i2s_init(void)  { -	return snd_soc_register_dai(&s3c24xx_i2s_dai); +	return platform_driver_register(&s3c24xx_iis_driver);  }  module_init(s3c24xx_i2s_init);  static void __exit s3c24xx_i2s_exit(void)  { -	snd_soc_unregister_dai(&s3c24xx_i2s_dai); +	platform_driver_unregister(&s3c24xx_iis_driver);  }  module_exit(s3c24xx_i2s_exit); @@ -501,3 +516,4 @@ module_exit(s3c24xx_i2s_exit);  MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");  MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c24xx-iis"); diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h index 726d91cf4e1c..f9ca04edacb7 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.h +++ b/sound/soc/s3c24xx/s3c24xx-i2s.h @@ -32,6 +32,4 @@  u32 s3c24xx_i2s_get_clockrate(void); -extern struct snd_soc_dai s3c24xx_i2s_dai; -  #endif /*S3C24XXI2S_H_*/ diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index 4984754f3298..c4c111442010 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c @@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {  		       speaker_unmute_get, speaker_unmute_put),  }; -void simtec_audio_init(struct snd_soc_codec *codec) +void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	if (pdata->amp_gpio > 0) {  		pr_debug("%s: adding amp routes\n", __func__); @@ -170,8 +172,8 @@ static int simtec_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret;  	/* Set the CODEC as the bus clock master, I2S */ @@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops);  #endif  int __devinit simtec_audio_core_probe(struct platform_device *pdev, -				      struct snd_soc_device *socdev) +				      struct snd_soc_card *card)  {  	struct platform_device *snd_dev;  	int ret; -	socdev->card->dai_link->ops = &simtec_snd_ops; +	card->dai_link->ops = &simtec_snd_ops;  	pdata = pdev->dev.platform_data;  	if (!pdata) { @@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev,  		goto err_gpio;  	} -	platform_set_drvdata(snd_dev, socdev); -	socdev->dev = &snd_dev->dev; +	platform_set_drvdata(snd_dev, card);  	ret = platform_device_add(snd_dev);  	if (ret) { diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index e18faee30cce..e63d5ff9c41f 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h @@ -7,10 +7,10 @@   * published by the Free Software Foundation.  */ -extern void simtec_audio_init(struct snd_soc_codec *codec); +extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd);  extern int simtec_audio_core_probe(struct platform_device *pdev, -				   struct snd_soc_device *socdev); +				   struct snd_soc_card *card);  extern int simtec_audio_remove(struct platform_device *pdev); diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c index bdf8951af8e3..f88453735ae2 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c @@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = {   * Attach our controls and configure the necessary codec   * mappings for our sound card instance.  */ -static int simtec_hermes_init(struct snd_soc_codec *codec) +static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_new_controls(codec, dapm_widgets,  				  ARRAY_SIZE(dapm_widgets)); @@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec)  	snd_soc_dapm_enable_pin(codec, "Line Out");  	snd_soc_dapm_enable_pin(codec, "Mic Jack"); -	simtec_audio_init(codec); +	simtec_audio_init(rtd);  	snd_soc_dapm_sync(codec);  	return 0;  } -static struct aic3x_setup_data codec_setup = { -}; -  static struct snd_soc_dai_link simtec_dai_aic33 = {  	.name		= "tlv320aic33",  	.stream_name	= "TLV320AIC33", -	.cpu_dai	= &s3c24xx_i2s_dai, -	.codec_dai	= &aic3x_dai, +	.codec_name	= "tlv320aic3x-codec.0-0x1a", +	.cpu_dai_name	= "s3c24xx-i2s", +	.codec_dai_name = "tlv320aic3x-hifi", +	.platform_name	= "s3c24xx-pcm-audio",  	.init		= simtec_hermes_init,  };  /* simtec audio machine driver */  static struct snd_soc_card snd_soc_machine_simtec_aic33 = {  	.name		= "Simtec-Hermes", -	.platform	= &s3c24xx_soc_platform,  	.dai_link	= &simtec_dai_aic33,  	.num_links	= 1,  }; -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic33 = { -	.card		= &snd_soc_machine_simtec_aic33, -	.codec_dev	= &soc_codec_dev_aic3x, -	.codec_data	= &codec_setup, -}; -  static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)  {  	dev_info(&pd->dev, "probing....\n"); -	return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); +	return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);  }  static struct platform_driver simtec_audio_hermes_platdrv = { diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c index 185c0acb5ce6..c0967593510d 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c @@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = {   * Attach our controls and configure the necessary codec   * mappings for our sound card instance.  */ -static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) +static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_new_controls(codec, dapm_widgets,  				  ARRAY_SIZE(dapm_widgets)); @@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)  	snd_soc_dapm_enable_pin(codec, "Line Out");  	snd_soc_dapm_enable_pin(codec, "Mic Jack"); -	simtec_audio_init(codec); +	simtec_audio_init(rtd);  	snd_soc_dapm_sync(codec);  	return 0; @@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link simtec_dai_aic23 = {  	.name		= "tlv320aic23",  	.stream_name	= "TLV320AIC23", -	.cpu_dai	= &s3c24xx_i2s_dai, -	.codec_dai	= &tlv320aic23_dai, +	.codec_name	= "tlv320aic3x-codec.0-0x1a", +	.cpu_dai_name	= "s3c24xx-i2s", +	.codec_dai_name = "tlv320aic3x-hifi", +	.platform_name	= "s3c24xx-pcm-audio",  	.init		= simtec_tlv320aic23_init,  };  /* simtec audio machine driver */  static struct snd_soc_card snd_soc_machine_simtec_aic23 = {  	.name		= "Simtec", -	.platform	= &s3c24xx_soc_platform,  	.dai_link	= &simtec_dai_aic23,  	.num_links	= 1,  }; -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic23 = { -	.card		= &snd_soc_machine_simtec_aic23, -	.codec_dev	= &soc_codec_dev_tlv320aic23, -}; -  static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)  { -	return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); +	return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);  }  static struct platform_driver simtec_audio_tlv320aic23_platdrv = { diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c index 052d59659c29..bd48ffbde880 100644 --- a/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c @@ -133,8 +133,8 @@ static int s3c24xx_uda134x_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	unsigned int clk = 0;  	int ret = 0;  	int clk_source, fs_mode; @@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = {  static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {  	.name = "UDA134X",  	.stream_name = "UDA134X", -	.codec_dai = &uda134x_dai, -	.cpu_dai = &s3c24xx_i2s_dai, +	.codec_name = "uda134x-hifi", +	.codec_dai_name = "uda134x-hifi", +	.cpu_dai_name = "s3c24xx-i2s",  	.ops = &s3c24xx_uda134x_ops, +	.platform_name	= "s3c24xx-pcm-audio",  };  static struct snd_soc_card snd_soc_s3c24xx_uda134x = {  	.name = "S3C24XX_UDA134X", -	.platform = &s3c24xx_soc_platform,  	.dai_link = &s3c24xx_uda134x_dai_link,  	.num_links = 1,  }; @@ -256,6 +257,7 @@ static void setmode(int v)  	gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);  } +/* FIXME - This must be codec platform data but in which board file ?? */  static struct uda134x_platform_data s3c24xx_uda134x = {  	.l3 = {  		.setdat = setdat, @@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = {  	},  }; -static struct snd_soc_device s3c24xx_uda134x_snd_devdata = { -	.card = &snd_soc_s3c24xx_uda134x, -	.codec_dev = &soc_codec_dev_uda134x, -	.codec_data = &s3c24xx_uda134x, -}; -  static int s3c24xx_uda134x_setup_pin(int pin, char *fun)  {  	if (gpio_request(pin, "s3c24xx_uda134x") < 0) { @@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)  	}  	platform_set_drvdata(s3c24xx_uda134x_snd_device, -			     &s3c24xx_uda134x_snd_devdata); -	s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev; +			     &snd_soc_s3c24xx_uda134x);  	ret = platform_device_add(s3c24xx_uda134x_snd_device);  	if (ret) {  		printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 06db130030a1..a13415a85a45 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c @@ -16,9 +16,7 @@  #include <sound/soc.h>  #include <sound/pcm_params.h> -#include <mach/gpio-bank-c.h> -#include <mach/gpio-bank-h.h> -#include <plat/gpio-cfg.h> +#include <plat/audio.h>  #include <mach/map.h>  #include <mach/dma.h> @@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out;  static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in;  static struct s3c_i2sv2_info s3c64xx_i2sv4; -struct snd_soc_dai s3c64xx_i2s_v4_dai; -EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) +static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai)  { -	return cpu_dai->private_data; -} +	struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; +	int ret = 0; -static int s3c64xx_i2sv4_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) -{ -	/* configure GPIO for i2s port */ -	s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); -	s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); -	s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); -	s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); -	s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); -	s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); -	s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); +	snd_soc_dai_set_drvdata(dai, i2s); -	return 0; +	ret = s3c_i2sv2_probe(dai, i2s, i2s->base); + +	return ret;  }  static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream,  				 struct snd_pcm_hw_params *params,  				 struct snd_soc_dai *cpu_dai)  { -	struct s3c_i2sv2_info *i2s = to_info(cpu_dai); +	struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);  	struct s3c_dma_params *dma_data;  	u32 iismod; @@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = {  	.hw_params	= s3c_i2sv4_hw_params,  }; +static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = { +	.symmetric_rates = 1, +	.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, +	}, +	.probe = s3c64xx_i2sv4_probe, +	.ops = &s3c64xx_i2sv4_dai_ops, +}; +  static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)  { +	struct s3c_audio_pdata *i2s_pdata;  	struct s3c_i2sv2_info *i2s; -	struct snd_soc_dai *dai; +	struct resource *res;  	int ret;  	i2s = &s3c64xx_i2sv4; -	dai = &s3c64xx_i2s_v4_dai; - -	if (dai->dev) { -		dev_dbg(dai->dev, "%s: \ -			I2Sv4 instance already registered!\n", __func__); -		return -EBUSY; -	} - -	dai->dev = &pdev->dev; -	dai->name = "s3c64xx-i2s-v4"; -	dai->id = 0; -	dai->symmetric_rates = 1; -	dai->playback.channels_min = 2; -	dai->playback.channels_max = 2; -	dai->playback.rates = S3C64XX_I2S_RATES; -	dai->playback.formats = S3C64XX_I2S_FMTS; -	dai->capture.channels_min = 2; -	dai->capture.channels_max = 2; -	dai->capture.rates = S3C64XX_I2S_RATES; -	dai->capture.formats = S3C64XX_I2S_FMTS; -	dai->probe = s3c64xx_i2sv4_probe; -	dai->ops = &s3c64xx_i2sv4_dai_ops;  	i2s->feature |= S3C_FEATURE_CDCLKCON;  	i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in;  	i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; -	i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; -	i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; -	i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; -	i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; +	res = platform_get_resource(pdev, IORESOURCE_DMA, 0); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); +		return -ENXIO; +	} +	i2s->dma_playback->channel = res->start; + +	res = platform_get_resource(pdev, IORESOURCE_DMA, 1); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); +		return -ENXIO; +	} +	i2s->dma_capture->channel = res->start; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); +		return -ENXIO; +	} + +	if (!request_mem_region(res->start, resource_size(res), +				"s3c64xx-i2s-v4")) { +		dev_err(&pdev->dev, "Unable to request SFR region\n"); +		return -EBUSY; +	} +	i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; +	i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;  	i2s->dma_capture->client = &s3c64xx_dma_client_in;  	i2s->dma_capture->dma_size = 4;  	i2s->dma_playback->client = &s3c64xx_dma_client_out;  	i2s->dma_playback->dma_size = 4; +	i2s->base = res->start; + +	i2s_pdata = pdev->dev.platform_data; +	if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { +		dev_err(&pdev->dev, "Unable to configure gpio\n"); +		return -EINVAL; +	} +  	i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");  	if (IS_ERR(i2s->iis_cclk)) {  		dev_err(&pdev->dev, "failed to get audio-bus\n"); @@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)  	clk_enable(i2s->iis_cclk); -	ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); -	if (ret) -		goto err_clk; - -	ret = s3c_i2sv2_register_dai(dai); +	ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai);  	if (ret != 0)  		goto err_i2sv2;  	return 0;  err_i2sv2: -	/* Not implemented for I2Sv2 core yet */ -err_clk:  	clk_put(i2s->iis_cclk);  err:  	return ret; @@ -178,7 +187,7 @@ err:  static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev)  { -	dev_err(&pdev->dev, "Device removal not yet supported\n"); +	snd_soc_unregister_dai(&pdev->dev);  	return 0;  } @@ -207,3 +216,4 @@ module_exit(s3c64xx_i2sv4_exit);  MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");  MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c64xx-iis-v4"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 1d85cb85a7d2..ae7acb6c4f1d 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -12,15 +12,15 @@   * published by the Free Software Foundation.   */ +#include <linux/module.h>  #include <linux/clk.h>  #include <linux/gpio.h>  #include <linux/io.h> +#include <linux/slab.h>  #include <sound/soc.h> -#include <mach/gpio-bank-d.h> -#include <mach/gpio-bank-e.h> -#include <plat/gpio-cfg.h> +#include <plat/audio.h>  #include <mach/map.h>  #include <mach/dma.h> @@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];  static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];  static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; -struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3]; -EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) +struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)  { -	return cpu_dai->private_data; +	struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); +	u32 iismod = readl(i2s->regs + S3C2412_IISMOD); + +	if (iismod & S3C2412_IISMOD_IMS_SYSMUX) +		return i2s->iis_cclk; +	else +		return i2s->iis_pclk;  } +EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); -static int s3c64xx_i2s_probe(struct platform_device *pdev, -			     struct snd_soc_dai *dai) +static int s3c64xx_i2s_probe(struct snd_soc_dai *dai)  { -	/* configure GPIO for i2s port */ -	switch (dai->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); +	struct s3c_i2sv2_info *i2s; +	int ret; + +	if (dai->id >= MAX_I2SV3) { +		dev_err(dai->dev, "id %d out of range\n", dai->id); +		return -EINVAL; +	} + +	i2s = &s3c64xx_i2s[dai->id]; +	snd_soc_dai_set_drvdata(dai, i2s); + +	i2s->iis_cclk = clk_get(dai->dev, "audio-bus"); +	if (IS_ERR(i2s->iis_cclk)) { +		dev_err(dai->dev, "failed to get audio-bus\n"); +		ret = PTR_ERR(i2s->iis_cclk); +		goto err;  	} +	clk_enable(i2s->iis_cclk); + +	ret = s3c_i2sv2_probe(dai, i2s, i2s->base); +	if (ret) +		goto err_clk; +  	return 0; + +err_clk: +	clk_disable(i2s->iis_cclk); +	clk_put(i2s->iis_cclk); +err: +	kfree(i2s); +	return ret;  } +static int s3c64xx_i2s_remove(struct snd_soc_dai *dai) +{ +	struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); + +	clk_disable(i2s->iis_cclk); +	clk_put(i2s->iis_cclk); +	kfree(i2s); +	return 0; +}  static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; +static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = { +{ +	.name = "s3c64xx-i2s-0", +	.probe = s3c64xx_i2s_probe, +	.remove = s3c64xx_i2s_remove, +	.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 = &s3c64xx_i2s_dai_ops, +	.symmetric_rates = 1, +}, { +	.name = "s3c64xx-i2s-1", +	.probe = s3c64xx_i2s_probe, +	.remove = s3c64xx_i2s_remove, +	.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 = &s3c64xx_i2s_dai_ops, +	.symmetric_rates = 1, +},}; +  static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)  { +	struct s3c_audio_pdata *i2s_pdata;  	struct s3c_i2sv2_info *i2s; -	struct snd_soc_dai *dai; -	int ret; +	struct resource *res; +	int i, ret;  	if (pdev->id >= MAX_I2SV3) {  		dev_err(&pdev->dev, "id %d out of range\n", pdev->id); @@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)  	}  	i2s = &s3c64xx_i2s[pdev->id]; -	dai = &s3c64xx_i2s_dai[pdev->id]; -	dai->dev = &pdev->dev; -	dai->name = "s3c64xx-i2s"; -	dai->id = pdev->id; -	dai->symmetric_rates = 1; -	dai->playback.channels_min = 2; -	dai->playback.channels_max = 2; -	dai->playback.rates = S3C64XX_I2S_RATES; -	dai->playback.formats = S3C64XX_I2S_FMTS; -	dai->capture.channels_min = 2; -	dai->capture.channels_max = 2; -	dai->capture.rates = S3C64XX_I2S_RATES; -	dai->capture.formats = S3C64XX_I2S_FMTS; -	dai->probe = s3c64xx_i2s_probe; -	dai->ops = &s3c64xx_i2s_dai_ops; - -	i2s->feature |= S3C_FEATURE_CDCLKCON;  	i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];  	i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; -	if (pdev->id == 0) { -		i2s->dma_capture->channel = DMACH_I2S0_IN; -		i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD; -		i2s->dma_playback->channel = DMACH_I2S0_OUT; -		i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD; -	} else { -		i2s->dma_capture->channel = DMACH_I2S1_IN; -		i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD; -		i2s->dma_playback->channel = DMACH_I2S1_OUT; -		i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD; +	res = platform_get_resource(pdev, IORESOURCE_DMA, 0); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); +		return -ENXIO; +	} +	i2s->dma_playback->channel = res->start; + +	res = platform_get_resource(pdev, IORESOURCE_DMA, 1); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); +		return -ENXIO; +	} +	i2s->dma_capture->channel = res->start; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) { +		dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); +		return -ENXIO;  	} +	if (!request_mem_region(res->start, resource_size(res), +				"s3c64xx-i2s")) { +		dev_err(&pdev->dev, "Unable to request SFR region\n"); +		return -EBUSY; +	} +	i2s->base = res->start; + +	i2s_pdata = pdev->dev.platform_data; +	if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { +		dev_err(&pdev->dev, "Unable to configure gpio\n"); +		return -EINVAL; +	} +	i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; +	i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; +  	i2s->dma_capture->client = &s3c64xx_dma_client_in;  	i2s->dma_capture->dma_size = 4;  	i2s->dma_playback->client = &s3c64xx_dma_client_out;  	i2s->dma_playback->dma_size = 4; -	i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); -	if (IS_ERR(i2s->iis_cclk)) { -		dev_err(&pdev->dev, "failed to get audio-bus\n"); -		ret = PTR_ERR(i2s->iis_cclk); -		goto err; +	for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) { +		ret = s3c_i2sv2_register_dai(&pdev->dev, i, +						&s3c64xx_i2s_dai[i]); +		if (ret != 0) +			return ret;  	} -	clk_enable(i2s->iis_cclk); - -	ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); -	if (ret) -		goto err_clk; - -	ret = s3c_i2sv2_register_dai(dai); -	if (ret != 0) -		goto err_i2sv2; -  	return 0; - -err_i2sv2: -	/* Not implemented for I2Sv2 core yet */ -err_clk: -	clk_put(i2s->iis_cclk); -err: -	return ret;  }  static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)  { -	dev_err(&pdev->dev, "Device removal not yet supported\n"); +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai));  	return 0;  } @@ -188,3 +239,4 @@ module_exit(s3c64xx_i2s_exit);  MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");  MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c64xx-iis"); diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index 7a40f43d1d51..19bd444bf8a6 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h @@ -36,7 +36,5 @@ struct clk;  	(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\  	 SNDRV_PCM_FMTBIT_S24_LE) -extern struct snd_soc_dai s3c64xx_i2s_dai[]; -extern struct snd_soc_dai s3c64xx_i2s_v4_dai;  #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c index b480348140b0..dd20ca7f4681 100644 --- a/sound/soc/s3c24xx/smartq_wm8987.c +++ b/sound/soc/s3c24xx/smartq_wm8987.c @@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = {  	{  		.name		= "wm8987",  		.stream_name	= "SmartQ Hi-Fi", -		.cpu_dai	= &s3c64xx_i2s_dai[0], -		.codec_dai	= &wm8750_dai, +		.cpu_dai_name	= "s3c64xx-i2s.0", +		.codec_dai_name	= "wm8750-hifi", +		.platform_name	= "s3c24xx-pcm-audio", +		.codec_name	= "wm8750-codec.0-0x1a",  		.init		= smartq_wm8987_init,  		.ops		= &smartq_hifi_ops,  	}, @@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = {  static struct snd_soc_card snd_soc_smartq = {  	.name = "SmartQ", -	.platform = &s3c24xx_soc_platform,  	.dai_link = smartq_dai,  	.num_links = ARRAY_SIZE(smartq_dai),  }; -static struct snd_soc_device smartq_snd_devdata = { -	.card = &snd_soc_smartq, -	.codec_dev = &soc_codec_dev_wm8750, -}; -  static struct platform_device *smartq_snd_device;  static int __init smartq_init(void) @@ -245,8 +241,7 @@ static int __init smartq_init(void)  	if (!smartq_snd_device)  		return -ENOMEM; -	platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata); -	smartq_snd_devdata.dev = &smartq_snd_device->dev; +	platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);  	ret = platform_device_add(smartq_snd_device);  	if (ret) { diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c index 362258835e8d..66f9e222220b 100644 --- a/sound/soc/s3c24xx/smdk2443_wm9710.c +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c @@ -19,7 +19,6 @@  #include <sound/soc.h>  #include <sound/soc-dapm.h> -#include "../codecs/ac97.h"  #include "s3c-dma.h"  #include "s3c-ac97.h" @@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = {  {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], -	.codec_dai = &ac97_dai, +	.cpu_dai_name = "s3c-ac97-dai", +	.codec_dai_name = "ac97-hifi", +	.codec_name = "ac97-codec", +	.platform_name = "s3c24xx-pcm-audio",  },  };  static struct snd_soc_card smdk2443 = {  	.name = "SMDK2443", -	.platform = &s3c24xx_soc_platform,  	.dai_link = smdk2443_dai,  	.num_links = ARRAY_SIZE(smdk2443_dai),  }; -static struct snd_soc_device smdk2443_snd_ac97_devdata = { -	.card = &smdk2443, -	.codec_dev = &soc_codec_dev_ac97, -}; -  static struct platform_device *smdk2443_snd_ac97_device;  static int __init smdk2443_init(void) @@ -56,9 +51,7 @@ static int __init smdk2443_init(void)  	if (!smdk2443_snd_ac97_device)  		return -ENOMEM; -	platform_set_drvdata(smdk2443_snd_ac97_device, -				&smdk2443_snd_ac97_devdata); -	smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; +	platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443);  	ret = platform_device_add(smdk2443_snd_ac97_device);  	if (ret) diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 4926acaaa8b0..5c21e26da075 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c @@ -35,8 +35,8 @@ static int smdk64xx_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 *cpu_dai = rtd->dai->cpu_dai; -	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	unsigned int pll_out;  	int bfs, rfs, ret; @@ -180,8 +180,10 @@ static const struct snd_soc_dapm_route audio_map_rx[] = {  	{"Rear", NULL, "VOUT3R"},  }; -static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) +static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	/* Add smdk64xx specific Capture widgets */  	snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,  				  ARRAY_SIZE(wm8580_dapm_widgets_cpt)); @@ -200,8 +202,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)  	return 0;  } -static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec) +static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	/* Add smdk64xx specific Playback widgets */  	snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,  				  ARRAY_SIZE(wm8580_dapm_widgets_pbk)); @@ -219,16 +223,20 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {  { /* Primary Playback i/f */  	.name = "WM8580 PAIF RX",  	.stream_name = "Playback", -	.cpu_dai = &s3c64xx_i2s_v4_dai, -	.codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], +	.cpu_dai_name = "s3c64xx-iis-v4", +	.codec_dai_name = "wm8580-hifi-playback", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8580-codec.0-001b",  	.init = smdk64xx_wm8580_init_paifrx,  	.ops = &smdk64xx_ops,  },  { /* Primary Capture i/f */  	.name = "WM8580 PAIF TX",  	.stream_name = "Capture", -	.cpu_dai = &s3c64xx_i2s_v4_dai, -	.codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], +	.cpu_dai_name = "s3c64xx-iis-v4", +	.codec_dai_name = "wm8580-hifi-capture", +	.platform_name = "s3c24xx-pcm-audio", +	.codec_name = "wm8580-codec.0-001b",  	.init = smdk64xx_wm8580_init_paiftx,  	.ops = &smdk64xx_ops,  }, @@ -236,16 +244,10 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {  static struct snd_soc_card smdk64xx = {  	.name = "smdk64xx", -	.platform = &s3c24xx_soc_platform,  	.dai_link = smdk64xx_dai,  	.num_links = ARRAY_SIZE(smdk64xx_dai),  }; -static struct snd_soc_device smdk64xx_snd_devdata = { -	.card = &smdk64xx, -	.codec_dev = &soc_codec_dev_wm8580, -}; -  static struct platform_device *smdk64xx_snd_device;  static int __init smdk64xx_audio_init(void) @@ -256,8 +258,7 @@ static int __init smdk64xx_audio_init(void)  	if (!smdk64xx_snd_device)  		return -ENOMEM; -	platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata); -	smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev; +	platform_set_drvdata(smdk64xx_snd_device, &smdk64xx);  	ret = platform_device_add(smdk64xx_snd_device);  	if (ret) diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c index 5527b9e88c98..90108a7a0a8e 100644 --- a/sound/soc/s3c24xx/smdk_wm9713.c +++ b/sound/soc/s3c24xx/smdk_wm9713.c @@ -46,40 +46,50 @@ static struct snd_soc_card smdk;  static struct snd_soc_dai_link smdk_dai = {  	.name = "AC97",  	.stream_name = "AC97 PCM", -	.cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], -	.codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], +	.platform_name = "s3c24xx-pcm-audio", +	.cpu_dai_name = "s3c-ac97-dai", +	.codec_dai_name = "wm9713-hifi", +	.codec_name = "wm9713-codec",  };  static struct snd_soc_card smdk = {  	.name = "SMDK", -	.platform = &s3c24xx_soc_platform,  	.dai_link = &smdk_dai,  	.num_links = 1,  }; -static struct snd_soc_device smdk_snd_ac97_devdata = { -	.card = &smdk, -	.codec_dev = &soc_codec_dev_wm9713, -}; - +static struct platform_device *smdk_snd_wm9713_device;  static struct platform_device *smdk_snd_ac97_device;  static int __init smdk_init(void)  {  	int ret; -	smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); -	if (!smdk_snd_ac97_device) +	smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); +	if (!smdk_snd_wm9713_device)  		return -ENOMEM; -	platform_set_drvdata(smdk_snd_ac97_device, -			     &smdk_snd_ac97_devdata); -	smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev; +	ret = platform_device_add(smdk_snd_wm9713_device); +	if (ret) +		goto err; + +	smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); +	if (!smdk_snd_ac97_device) { +		ret = -ENOMEM; +		goto err; +	} + +	platform_set_drvdata(smdk_snd_ac97_device, &smdk);  	ret = platform_device_add(smdk_snd_ac97_device); -	if (ret) +	if (ret) {  		platform_device_put(smdk_snd_ac97_device); +		goto err; +	} +	return 0; +err: +	platform_device_put(smdk_snd_wm9713_device);  	return ret;  } diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 59e3fa7bcb05..8778faa174a6 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -140,7 +140,7 @@ static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)  static void s6000_i2s_start(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	int channel;  	channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -152,7 +152,7 @@ static void s6000_i2s_start(struct snd_pcm_substream *substream)  static void s6000_i2s_stop(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);  	int channel;  	channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -194,7 +194,7 @@ static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)  static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)  { -	struct s6000_i2s_dev *dev = cpu_dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	unsigned int errors;  	unsigned int ret; @@ -232,7 +232,7 @@ static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)  static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,  				   unsigned int fmt)  { -	struct s6000_i2s_dev *dev = cpu_dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);  	u32 w;  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -273,7 +273,7 @@ static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,  static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)  { -	struct s6000_i2s_dev *dev = dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);  	if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)  		return -EINVAL; @@ -287,7 +287,7 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,  			       struct snd_pcm_hw_params *params,  			       struct snd_soc_dai *dai)  { -	struct s6000_i2s_dev *dev = dai->private_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);  	int interf;  	u32 w = 0; @@ -326,15 +326,17 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,  	return 0;  } -static int s6000_i2s_dai_probe(struct platform_device *pdev, -			       struct snd_soc_dai *dai) +static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)  { -	struct s6000_i2s_dev *dev = dai->private_data; -	struct s6000_snd_platform_data *pdata = pdev->dev.platform_data; +	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); +	struct s6000_snd_platform_data *pdata = dai->dev->platform_data;  	if (!pdata)  		return -EINVAL; +	dai->capture_dma_data = &dev->dma_params; +	dai->playback_dma_data = &dev->dma_params; +  	dev->wide = pdata->wide;  	dev->channel_in = pdata->channel_in;  	dev->channel_out = pdata->channel_out; @@ -352,10 +354,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,  		dev->channel_in = 0;  		dev->channel_out = 1; -		dai->capture.channels_min = 2 * dev->lines_in; -		dai->capture.channels_max = dai->capture.channels_min; -		dai->playback.channels_min = 2 * dev->lines_out; -		dai->playback.channels_max = dai->playback.channels_min; +		dai->driver->capture.channels_min = 2 * dev->lines_in; +		dai->driver->capture.channels_max = dai->driver->capture.channels_min; +		dai->driver->playback.channels_min = 2 * dev->lines_out; +		dai->driver->playback.channels_max = dai->driver->playback.channels_min;  		for (i = 0; i < dev->lines_out; i++)  			s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); @@ -372,10 +374,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,  		if (dev->lines_in > 1 || dev->lines_out > 1)  			return -EINVAL; -		dai->capture.channels_min = 2 * dev->lines_in; -		dai->capture.channels_max = 8 * dev->lines_in; -		dai->playback.channels_min = 2 * dev->lines_out; -		dai->playback.channels_max = 8 * dev->lines_out; +		dai->driver->capture.channels_min = 2 * dev->lines_in; +		dai->driver->capture.channels_max = 8 * dev->lines_in; +		dai->driver->playback.channels_min = 2 * dev->lines_out; +		dai->driver->playback.channels_max = 8 * dev->lines_out;  		if (dev->lines_in)  			cfg[dev->channel_in] = S6_I2S_IN; @@ -413,9 +415,7 @@ static struct snd_soc_dai_ops s6000_i2s_dai_ops = {  	.hw_params = s6000_i2s_hw_params,  }; -struct snd_soc_dai s6000_i2s_dai = { -	.name = "s6000-i2s", -	.id = 0, +static struct snd_soc_dai_driver s6000_i2s_dai = {  	.probe = s6000_i2s_dai_probe,  	.playback = {  		.channels_min = 2, @@ -435,7 +435,6 @@ struct snd_soc_dai s6000_i2s_dai = {  	},  	.ops = &s6000_i2s_dai_ops,  } -EXPORT_SYMBOL_GPL(s6000_i2s_dai);  static int __devinit s6000_i2s_probe(struct platform_device *pdev)  { @@ -513,11 +512,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)  		ret = -ENOMEM;  		goto err_release_dma2;  	} - -	s6000_i2s_dai.dev = &pdev->dev; -	s6000_i2s_dai.private_data = dev; -	s6000_i2s_dai.capture.dma_data = &dev->dma_params; -	s6000_i2s_dai.playback.dma_data = &dev->dma_params; +	dev_set_drvdata(&pdev->dev, dev);  	dev->sifbase = sifmem->start;  	dev->scbbase = mmio; @@ -548,7 +543,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)  			 S6_I2S_INT_UNDERRUN |  			 S6_I2S_INT_OVERRUN); -	ret = snd_soc_register_dai(&s6000_i2s_dai); +	ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai);  	if (ret)  		goto err_release_dev; @@ -573,17 +568,16 @@ err_release_none:  static void __devexit s6000_i2s_remove(struct platform_device *pdev)  { -	struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data; +	struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);  	struct resource *region;  	void __iomem *mmio = dev->scbbase; -	snd_soc_unregister_dai(&s6000_i2s_dai); +	snd_soc_unregister_dai(&pdev->dev);  	s6000_i2s_stop_channel(dev, 0);  	s6000_i2s_stop_channel(dev, 1);  	s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); -	s6000_i2s_dai.private_data = 0;  	kfree(dev);  	region = platform_get_resource(pdev, IORESOURCE_DMA, 0); diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h index 2375fdfe6dba..86aa1921c89e 100644 --- a/sound/soc/s6000/s6000-i2s.h +++ b/sound/soc/s6000/s6000-i2s.h @@ -12,8 +12,6 @@  #ifndef _S6000_I2S_H  #define _S6000_I2S_H -extern struct snd_soc_dai s6000_i2s_dai; -  struct s6000_snd_platform_data {  	int lines_in;  	int lines_out; diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 9c7f7f00cebb..271fd222bf19 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)  	dma_addr_t dma_pos;  	dma_addr_t src, dst; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	period_size = snd_pcm_lib_period_bytes(substream);  	dma_offset = prtd->period * period_size; @@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)  {  	struct snd_pcm *pcm = data;  	struct snd_soc_pcm_runtime *runtime = pcm->private_data; -	struct s6000_pcm_dma_params *params = -		snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);  	struct s6000_runtime_data *prtd;  	unsigned int has_xrun;  	int i, ret = IRQ_NONE; -	u32 channel[2] = { -		[SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out, -		[SNDRV_PCM_STREAM_CAPTURE] = params->dma_in -	}; - -	has_xrun = params->check_xrun(runtime->dai->cpu_dai); -	for (i = 0; i < ARRAY_SIZE(channel); ++i) { +	for (i = 0; i < 2; ++i) {  		struct snd_pcm_substream *substream = pcm->streams[i].substream; +		struct s6000_pcm_dma_params *params = +					snd_soc_dai_get_dma_data(runtime->cpu_dai, substream); +		u32 channel;  		unsigned int pending; -		if (!channel[i]) +		if (substream == SNDRV_PCM_STREAM_PLAYBACK) +			channel = params->dma_out; +		else +			channel = params->dma_in; + +		has_xrun = params->check_xrun(runtime->cpu_dai); + +		if (!channel)  			continue;  		if (unlikely(has_xrun & (1 << i)) && @@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)  			ret = IRQ_HANDLED;  		} -		pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]), -					     DMA_INDEX_CHNL(channel[i])); +		pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), +					     DMA_INDEX_CHNL(channel));  		if (pending & 1) {  			ret = IRQ_HANDLED; @@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)  				   snd_pcm_running(substream))) {  				snd_pcm_period_elapsed(substream);  				dev_dbg(pcm->dev, "period elapsed %x %x\n", -				       s6dmac_cur_src(DMA_MASK_DMAC(channel[i]), -						   DMA_INDEX_CHNL(channel[i])), -				       s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]), -						   DMA_INDEX_CHNL(channel[i]))); +				       s6dmac_cur_src(DMA_MASK_DMAC(channel), +						   DMA_INDEX_CHNL(channel)), +				       s6dmac_cur_dst(DMA_MASK_DMAC(channel), +						   DMA_INDEX_CHNL(channel)));  				prtd = substream->runtime->private_data;  				spin_lock(&prtd->lock);  				s6000_pcm_enqueue_dma(substream); @@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)  			if (pending & (1 << 3))  				printk(KERN_WARNING  				       "s6000-pcm: DMA %x Underflow\n", -				       channel[i]); +				       channel);  			if (pending & (1 << 4))  				printk(KERN_WARNING  				       "s6000-pcm: DMA %x Overflow\n", -				       channel[i]); +				       channel);  			if (pending & 0x1e0)  				printk(KERN_WARNING  				       "s6000-pcm: DMA %x Master Error "  				       "(mask %x)\n", -				       channel[i], pending >> 5); +				       channel, pending >> 5);  		}  	} @@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream)  	int srcinc;  	u32 dma; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	spin_lock_irqsave(&prtd->lock, flags); @@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)  	unsigned long flags;  	u32 channel; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)  		channel = par->dma_out; @@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)  	struct s6000_pcm_dma_params *par;  	int ret; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	ret = par->trigger(substream, cmd, 0);  	if (ret < 0) @@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)  	unsigned int offset;  	dma_addr_t count; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	spin_lock_irqsave(&prtd->lock, flags); @@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream)  	struct s6000_runtime_data *prtd;  	int ret; -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);  	ret = snd_pcm_hw_constraint_step(runtime, 0, @@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,  		return ret;  	} -	par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	if (par->same_rate) {  		spin_lock(&par->lock); @@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;  	struct s6000_pcm_dma_params *par = -		snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);  	spin_lock(&par->lock);  	par->in_use &= ~(1 << substream->stream); @@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm)  {  	struct snd_soc_pcm_runtime *runtime = pcm->private_data;  	struct s6000_pcm_dma_params *params = -		snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +		snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);  	free_irq(params->irq, pcm);  	snd_pcm_lib_preallocate_free_for_all(pcm); @@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card,  	struct s6000_pcm_dma_params *params;  	int res; -	params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); +	params = snd_soc_dai_get_dma_data(runtime->cpu_dai, +			pcm->streams[0].substream);  	if (!card->dev->dma_mask)  		card->dev->dma_mask = &s6000_pcm_dmamask; @@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card,  	return 0;  } -struct snd_soc_platform s6000_soc_platform = { -	.name = 	"s6000-audio", -	.pcm_ops = 	&s6000_pcm_ops, +static struct snd_soc_platform_driver s6000_soc_platform = { +	.ops =		&s6000_pcm_ops,  	.pcm_new = 	s6000_pcm_new,  	.pcm_free = 	s6000_pcm_free,  }; -EXPORT_SYMBOL_GPL(s6000_soc_platform); -static int __init s6000_pcm_init(void) +static int __devinit s6000_soc_platform_probe(struct platform_device *pdev) +{ +	return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); +} + +static int __devexit s6000_soc_platform_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver s6000_pcm_driver = { +	.driver = { +			.name = "s6000-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = s6000_soc_platform_probe, +	.remove = __devexit_p(s6000_soc_platform_remove), +}; + +static int __init snd_s6000_pcm_init(void)  { -	return snd_soc_register_platform(&s6000_soc_platform); +	return platform_driver_register(&s6000_pcm_driver);  } -module_init(s6000_pcm_init); +module_init(snd_s6000_pcm_init); -static void __exit s6000_pcm_exit(void) +static void __exit snd_s6000_pcm_exit(void)  { -	snd_soc_unregister_platform(&s6000_soc_platform); +	platform_driver_unregister(&s6000_pcm_driver);  } -module_exit(s6000_pcm_exit); +module_exit(snd_s6000_pcm_exit);  MODULE_AUTHOR("Daniel Gloeckner");  MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h index 96f23f6f52bf..09d9b883e58b 100644 --- a/sound/soc/s6000/s6000-pcm.h +++ b/sound/soc/s6000/s6000-pcm.h @@ -30,6 +30,4 @@ struct s6000_pcm_dma_params {  	int rate;  }; -extern struct snd_soc_platform s6000_soc_platform; -  #endif diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index c1b40ac22c05..96c05e137538 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -32,8 +32,8 @@ static int s6105_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 snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	int ret = 0;  	/* set codec DAI configuration */ @@ -134,8 +134,10 @@ static const struct snd_kcontrol_new audio_out_mux = {  };  /* Logic for a aic3x as connected on the s6105 ip camera ref design */ -static int s6105_aic3x_init(struct snd_soc_codec *codec) +static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	/* Add s6105 specific widgets */  	snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,  				  ARRAY_SIZE(aic3x_dapm_widgets)); @@ -165,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)  	snd_soc_dapm_sync(codec); -	snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec)); +	snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec));  	return 0;  } @@ -174,8 +176,10 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link s6105_dai = {  	.name = "TLV320AIC31",  	.stream_name = "AIC31", -	.cpu_dai = &s6000_i2s_dai, -	.codec_dai = &aic3x_dai, +	.cpu_dai_name = "s6000-i2s", +	.codec_dai_name = "tlv320aic3x-hifi", +	.platform_name = "s6000-pcm-audio", +	.codec_name = "tlv320aic3x-codec.0-001a",  	.init = s6105_aic3x_init,  	.ops = &s6105_ops,  }; @@ -183,22 +187,10 @@ static struct snd_soc_dai_link s6105_dai = {  /* s6105 audio machine driver */  static struct snd_soc_card snd_soc_card_s6105 = {  	.name = "Stretch IP Camera", -	.platform = &s6000_soc_platform,  	.dai_link = &s6105_dai,  	.num_links = 1,  }; -/* s6105 audio private data */ -static struct aic3x_setup_data s6105_aic3x_setup = { -}; - -/* s6105 audio subsystem */ -static struct snd_soc_device s6105_snd_devdata = { -	.card = &snd_soc_card_s6105, -	.codec_dev = &soc_codec_dev_aic3x, -	.codec_data = &s6105_aic3x_setup, -}; -  static struct s6000_snd_platform_data __initdata s6105_snd_data = {  	.wide		= 0,  	.channel_in	= 0, @@ -227,8 +219,7 @@ static int __init s6105_init(void)  	if (!s6105_snd_device)  		return -ENOMEM; -	platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata); -	s6105_snd_devdata.dev = &s6105_snd_device->dev; +	platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);  	platform_device_add_data(s6105_snd_device, &s6105_snd_data,  				 sizeof(s6105_snd_data)); diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 0d8bdf07729c..c326d29992fe 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -137,7 +137,7 @@ static void camelot_rxdma(void *data)  static int camelot_pcm_open(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;  	int ret, dmairq; @@ -150,7 +150,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)  		ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam);  		if (unlikely(ret)) {  			pr_debug("audio unit %d irqs already taken!\n", -			     rtd->dai->cpu_dai->id); +			     rtd->cpu_dai->id);  			return -EBUSY;  		}  		(void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); @@ -159,7 +159,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)  		ret = dmabrg_request_irq(dmairq, camelot_txdma, cam);  		if (unlikely(ret)) {  			pr_debug("audio unit %d irqs already taken!\n", -			     rtd->dai->cpu_dai->id); +			     rtd->cpu_dai->id);  			return -EBUSY;  		}  		(void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); @@ -170,7 +170,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)  static int camelot_pcm_close(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;  	int dmairq; @@ -191,7 +191,7 @@ static int camelot_hw_params(struct snd_pcm_substream *substream,  			     struct snd_pcm_hw_params *hw_params)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;  	int ret; @@ -219,7 +219,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	pr_debug("PCM data: addr 0x%08ulx len %d\n",  		 (u32)runtime->dma_addr, runtime->dma_bytes); @@ -266,7 +266,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)  static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;  	switch (cmd) { @@ -293,7 +293,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; +	struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];  	int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;  	unsigned long pos; @@ -342,25 +342,44 @@ static int camelot_pcm_new(struct snd_card *card,  	return 0;  } -struct snd_soc_platform sh7760_soc_platform = { -	.name		= "sh7760-pcm", +static struct snd_soc_platform sh7760_soc_platform = {  	.pcm_ops 	= &camelot_pcm_ops,  	.pcm_new	= camelot_pcm_new,  	.pcm_free	= camelot_pcm_free,  }; -EXPORT_SYMBOL_GPL(sh7760_soc_platform); -static int __init sh7760_soc_platform_init(void) +static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&sh7760_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);  } -module_init(sh7760_soc_platform_init); -static void __exit sh7760_soc_platform_exit(void) +static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&sh7760_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0; +} + +static struct platform_driver sh7760_pcm_driver = { +	.driver = { +			.name = "sh7760-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = sh7760_soc_platform_probe, +	.remove = __devexit_p(sh7760_soc_platform_remove), +}; + +static int __init snd_sh7760_pcm_init(void) +{ +	return platform_driver_register(&sh7760_pcm_driver); +} +module_init(snd_sh7760_pcm_init); + +static void __exit snd_sh7760_pcm_exit(void) +{ +	platform_driver_unregister(&sh7760_pcm_driver);  } -module_exit(sh7760_soc_platform_exit); +module_exit(snd_sh7760_pcm_exit);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index dad575a22622..9e107a9c4010 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c @@ -11,17 +11,17 @@  #include <linux/platform_device.h>  #include <sound/sh_fsi.h> -#include <../sound/soc/codecs/ak4642.h> -static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) +static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_dai *dai = rtd->codec_dai;  	int ret; -	ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM); +	ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM);  	if (ret < 0)  		return ret; -	ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0); +	ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0);  	return ret;  } @@ -29,24 +29,20 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link fsi_dai_link = {  	.name		= "AK4642",  	.stream_name	= "AK4642", -	.cpu_dai	= &fsi_soc_dai[FSI_PORT_A], -	.codec_dai	= &ak4642_dai, +	.cpu_dai_name	= "fsia-dai", /* fsi A */ +	.codec_dai_name	= "ak4642-hifi", +	.platform_name	= "fsi-pcm-audio", +	.codec_name	= "ak4642-codec.0-0012",  	.init		= fsi_ak4642_dai_init,  	.ops		= NULL,  };  static struct snd_soc_card fsi_soc_card  = {  	.name		= "FSI", -	.platform	= &fsi_soc_platform,  	.dai_link	= &fsi_dai_link,  	.num_links	= 1,  }; -static struct snd_soc_device fsi_snd_devdata = { -	.card		= &fsi_soc_card, -	.codec_dev	= &soc_codec_dev_ak4642, -}; -  static struct platform_device *fsi_snd_device;  static int __init fsi_ak4642_init(void) @@ -57,9 +53,7 @@ static int __init fsi_ak4642_init(void)  	if (!fsi_snd_device)  		goto out; -	platform_set_drvdata(fsi_snd_device, -			     &fsi_snd_devdata); -	fsi_snd_devdata.dev = &fsi_snd_device->dev; +	platform_set_drvdata(fsi_snd_device, &fsi_soc_card);  	ret = platform_device_add(fsi_snd_device);  	if (ret) diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index 121bbb07bb03..4f9298f45215 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c @@ -12,11 +12,12 @@  #include <linux/platform_device.h>  #include <sound/sh_fsi.h> -#include "../codecs/da7210.h" -static int fsi_da7210_init(struct snd_soc_codec *codec) +static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)  { -	return snd_soc_dai_set_fmt(&da7210_dai, +	struct snd_soc_dai *dai = rtd->codec_dai; + +	return snd_soc_dai_set_fmt(dai,  				   SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |  				   SND_SOC_DAIFMT_CBM_CFM);  } @@ -24,23 +25,19 @@ static int fsi_da7210_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link fsi_da7210_dai = {  	.name		= "DA7210",  	.stream_name	= "DA7210", -	.cpu_dai	= &fsi_soc_dai[FSI_PORT_B], -	.codec_dai	= &da7210_dai, +	.cpu_dai_name	= "fsib-dai", /* FSI B */ +	.codec_dai_name	= "da7210-hifi", +	.platform_name	= "fsi-pcm-audio", +	.codec_name	= "da7210-codec.0-001a",  	.init		= fsi_da7210_init,  };  static struct snd_soc_card fsi_soc_card = {  	.name		= "FSI", -	.platform	= &fsi_soc_platform,  	.dai_link	= &fsi_da7210_dai,  	.num_links	= 1,  }; -static struct snd_soc_device fsi_da7210_snd_devdata = { -	.card		= &fsi_soc_card, -	.codec_dev	= &soc_codec_dev_da7210, -}; -  static struct platform_device *fsi_da7210_snd_device;  static int __init fsi_da7210_sound_init(void) @@ -51,8 +48,7 @@ static int __init fsi_da7210_sound_init(void)  	if (!fsi_da7210_snd_device)  		return -ENOMEM; -	platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata); -	fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev; +	platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);  	ret = platform_device_add(fsi_da7210_snd_device);  	if (ret)  		platform_device_put(fsi_da7210_snd_device); diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 58c6bec642de..abc6d8309609 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -271,16 +271,19 @@ static int fsi_is_port_a(struct fsi_priv *fsi)  static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai_link *machine = rtd->dai; -	return  machine->cpu_dai; +	return  rtd->cpu_dai;  }  static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)  {  	struct snd_soc_dai *dai = fsi_get_dai(substream); +	struct fsi_master *master = snd_soc_dai_get_drvdata(dai); -	return dai->private_data; +	if (dai->id == 0) +		return &master->fsia; +	else +		return &master->fsib;  }  static u32 fsi_get_info_flags(struct fsi_priv *fsi) @@ -1025,10 +1028,9 @@ static int fsi_pcm_new(struct snd_card *card,  ************************************************************************/ -struct snd_soc_dai fsi_soc_dai[] = { +static struct snd_soc_dai_driver fsi_soc_dai[] = {  	{ -		.name			= "FSIA", -		.id			= 0, +		.name			= "fsia-dai",  		.playback = {  			.rates		= FSI_RATES,  			.formats	= FSI_FMTS, @@ -1044,8 +1046,7 @@ struct snd_soc_dai fsi_soc_dai[] = {  		.ops = &fsi_dai_ops,  	},  	{ -		.name			= "FSIB", -		.id			= 1, +		.name			= "fsib-dai",  		.playback = {  			.rates		= FSI_RATES,  			.formats	= FSI_FMTS, @@ -1061,15 +1062,12 @@ struct snd_soc_dai fsi_soc_dai[] = {  		.ops = &fsi_dai_ops,  	},  }; -EXPORT_SYMBOL_GPL(fsi_soc_dai); -struct snd_soc_platform fsi_soc_platform = { -	.name		= "fsi-pcm", -	.pcm_ops 	= &fsi_pcm_ops, +static struct snd_soc_platform_driver fsi_soc_platform = { +	.ops		= &fsi_pcm_ops,  	.pcm_new	= fsi_pcm_new,  	.pcm_free	= fsi_pcm_free,  }; -EXPORT_SYMBOL_GPL(fsi_soc_platform);  /************************************************************************ @@ -1132,11 +1130,7 @@ static int fsi_probe(struct platform_device *pdev)  	pm_runtime_enable(&pdev->dev);  	pm_runtime_resume(&pdev->dev); - -	fsi_soc_dai[0].dev		= &pdev->dev; -	fsi_soc_dai[0].private_data	= &master->fsia; -	fsi_soc_dai[1].dev		= &pdev->dev; -	fsi_soc_dai[1].private_data	= &master->fsib; +	dev_set_drvdata(&pdev->dev, master);  	fsi_soft_all_reset(master); @@ -1147,13 +1141,13 @@ static int fsi_probe(struct platform_device *pdev)  		goto exit_iounmap;  	} -	ret = snd_soc_register_platform(&fsi_soc_platform); +	ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);  	if (ret < 0) {  		dev_err(&pdev->dev, "cannot snd soc register\n");  		goto exit_free_irq;  	} -	return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); +	return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));  exit_free_irq:  	free_irq(irq, master); @@ -1171,10 +1165,10 @@ static int fsi_remove(struct platform_device *pdev)  {  	struct fsi_master *master; -	master = fsi_get_master(fsi_soc_dai[0].private_data); +	master = dev_get_drvdata(&pdev->dev); -	snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); -	snd_soc_unregister_platform(&fsi_soc_platform); +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); +	snd_soc_unregister_platform(&pdev->dev);  	pm_runtime_disable(&pdev->dev); @@ -1183,11 +1177,6 @@ static int fsi_remove(struct platform_device *pdev)  	iounmap(master->base);  	kfree(master); -	fsi_soc_dai[0].dev		= NULL; -	fsi_soc_dai[0].private_data	= NULL; -	fsi_soc_dai[1].dev		= NULL; -	fsi_soc_dai[1].private_data	= NULL; -  	return 0;  } @@ -1233,7 +1222,7 @@ static struct platform_device_id fsi_id_table[] = {  static struct platform_driver fsi_driver = {  	.driver 	= { -		.name	= "sh_fsi", +		.name	= "fsi-pcm-audio",  		.pm	= &fsi_pm_ops,  	},  	.probe		= fsi_probe, diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 41db75af3c69..c87e3ff28a0a 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -239,8 +239,7 @@ static int hac_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 hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; +	struct hac_priv *hac = &hac_cpu_data[dai->id];  	int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;  	switch (params->msbits) { @@ -271,10 +270,9 @@ static struct snd_soc_dai_ops hac_dai_ops = {  	.hw_params	= hac_hw_params,  }; -struct snd_soc_dai sh4_hac_dai[] = { +static struct snd_soc_dai_driver sh4_hac_dai[] = {  { -	.name			= "HAC0", -	.id			= 0, +	.name			= "hac-dai.0",  	.ac97_control		= 1,  	.playback = {  		.rates		= AC97_RATES, @@ -292,8 +290,7 @@ struct snd_soc_dai sh4_hac_dai[] = {  },  #ifdef CONFIG_CPU_SUBTYPE_SH7760  { -	.name			= "HAC1", -	.ac97_control		= 1, +	.name			= "hac-dai.1",  	.id			= 1,  	.playback = {  		.rates		= AC97_RATES, @@ -312,19 +309,40 @@ struct snd_soc_dai sh4_hac_dai[] = {  },  #endif  }; -EXPORT_SYMBOL_GPL(sh4_hac_dai); -static int __init sh4_hac_init(void) +static int __devinit hac_soc_platform_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dais(&pdev->dev, sh4_hac_dai, +			ARRAY_SIZE(sh4_hac_dai)); +} + +static int __devexit hac_soc_platform_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai)); +	return 0; +} + +static struct platform_driver hac_pcm_driver = { +	.driver = { +			.name = "hac-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = hac_soc_platform_probe, +	.remove = __devexit_p(hac_soc_platform_remove), +}; + +static int __init sh4_hac_pcm_init(void)  { -	return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); +	return platform_driver_register(&hac_pcm_driver);  } -module_init(sh4_hac_init); +module_init(sh4_hac_pcm_init); -static void __exit sh4_hac_exit(void) +static void __exit sh4_hac_pcm_exit(void)  { -	snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); +	platform_driver_unregister(&hac_pcm_driver);  } -module_exit(sh4_hac_exit); +module_exit(sh4_hac_pcm_exit);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index b823a5c9b9bc..866d78fb8398 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -50,7 +50,7 @@ static int migor_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 *codec_dai = rtd->codec_dai;  	int ret;  	unsigned int rate = params_rate(params); @@ -68,7 +68,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,  	if (ret < 0)  		return ret; -	ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF | +	ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF |  				  SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);  	if (ret < 0)  		return ret; @@ -81,7 +81,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,  	clk_set_rate(&siumckb_clk, codec_freq);  	dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq); -	ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT, +	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, SIU_CLKB_EXT,  				     codec_freq / 2, SND_SOC_CLOCK_IN);  	if (!ret) @@ -93,7 +93,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,  static int migor_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; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	if (use_count) {  		use_count--; @@ -136,8 +136,10 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{ "Mic Bias", NULL, "External Microphone" },  }; -static int migor_dai_init(struct snd_soc_codec *codec) +static int migor_dai_init(struct snd_soc_pcm_runtime *rtd)  { +	struct snd_soc_codec *codec = rtd->codec; +  	snd_soc_dapm_new_controls(codec, migor_dapm_widgets,  				  ARRAY_SIZE(migor_dapm_widgets)); @@ -150,8 +152,10 @@ static int migor_dai_init(struct snd_soc_codec *codec)  static struct snd_soc_dai_link migor_dai = {  	.name = "wm8978",  	.stream_name = "WM8978", -	.cpu_dai = &siu_i2s_dai, -	.codec_dai = &wm8978_dai, +	.cpu_dai_name = "siu-i2s-dai", +	.codec_dai_name = "wm8978-hifi", +	.platform_name = "siu-pcm-audio", +	.codec_name = "wm8978-codec.0-001a",  	.ops = &migor_dai_ops,  	.init = migor_dai_init,  }; @@ -159,17 +163,10 @@ static struct snd_soc_dai_link migor_dai = {  /* migor audio machine driver */  static struct snd_soc_card snd_soc_migor = {  	.name = "Migo-R", -	.platform = &siu_platform,  	.dai_link = &migor_dai,  	.num_links = 1,  }; -/* migor audio subsystem */ -static struct snd_soc_device migor_snd_devdata = { -	.card = &snd_soc_migor, -	.codec_dev = &soc_codec_dev_wm8978, -}; -  static struct platform_device *migor_snd_device;  static int __init migor_init(void) @@ -187,9 +184,7 @@ static int __init migor_init(void)  		goto epdevalloc;  	} -	platform_set_drvdata(migor_snd_device, &migor_snd_devdata); - -	migor_snd_devdata.dev = &migor_snd_device->dev; +	platform_set_drvdata(migor_snd_device, &snd_soc_migor);  	ret = platform_device_add(migor_snd_device);  	if (ret) diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c index ce7f95b59de3..b897f7b96d89 100644 --- a/sound/soc/sh/sh7760-ac97.c +++ b/sound/soc/sh/sh7760-ac97.c @@ -15,41 +15,35 @@  #include <sound/soc-dapm.h>  #include <asm/io.h> -#include "../codecs/ac97.h" -  #define IPSEL 0xFE400034  /* platform specific structs can be declared here */ -extern struct snd_soc_dai sh4_hac_dai[2]; -extern struct snd_soc_platform sh7760_soc_platform; +extern struct snd_soc_dai_driver sh4_hac_dai[2]; +extern struct snd_soc_platform_driver sh7760_soc_platform; -static int machine_init(struct snd_soc_codec *codec) +static int machine_init(struct snd_soc_pcm_runtime *rtd)  { -	snd_soc_dapm_sync(codec); +	snd_soc_dapm_sync(rtd->codec);  	return 0;  }  static struct snd_soc_dai_link sh7760_ac97_dai = {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &sh4_hac_dai[0],	/* HAC0 */ -	.codec_dai = &ac97_dai, +	.cpu_dai_name = "hac-dai.0",	/* HAC0 */ +	.codec_dai_name = "ac97-hifi", +	.platform_name = "sh7760-pcm-audio", +	.codec_name = "ac97-codec",  	.init = machine_init,  	.ops = NULL,  };  static struct snd_soc_card sh7760_ac97_soc_machine  = {  	.name = "SH7760 AC97", -	.platform = &sh7760_soc_platform,  	.dai_link = &sh7760_ac97_dai,  	.num_links = 1,  }; -static struct snd_soc_device sh7760_ac97_snd_devdata = { -	.card = &sh7760_ac97_soc_machine, -	.codec_dev = &soc_codec_dev_ac97, -}; -  static struct platform_device *sh7760_ac97_snd_device;  static int __init sh7760_ac97_init(void) @@ -67,8 +61,7 @@ static int __init sh7760_ac97_init(void)  		goto out;  	platform_set_drvdata(sh7760_ac97_snd_device, -			     &sh7760_ac97_snd_devdata); -	sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev; +			     &sh7760_ac97_soc_machine);  	ret = platform_device_add(sh7760_ac97_snd_device);  	if (ret) diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h index 492b1cae24cc..aa239ff7310d 100644 --- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h @@ -181,8 +181,9 @@ static inline u32 siu_read32(u32 __iomem *addr)  #define SIU_BRGBSEL	(0x108 / sizeof(u32))  #define SIU_BRRB	(0x10c / sizeof(u32)) -extern struct snd_soc_platform siu_platform; -extern struct snd_soc_dai siu_i2s_dai; +extern struct snd_soc_platform_driver siu_platform; +extern struct snd_soc_dai_driver siu_i2s_dai; +extern struct siu_info *siu_i2s_data;  int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);  void siu_free_port(struct siu_port *port_info); diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index eeed5edd722b..827940a8e248 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -71,6 +71,9 @@ struct port_flag {  	struct format_flag	capture;  }; +struct siu_info *siu_i2s_data = NULL; +EXPORT_SYMBOL_GPL(siu_i2s_data); +  static struct port_flag siu_flags[SIU_PORT_NUM] = {  	[SIU_PORT_A] = {  		.playback = { @@ -104,13 +107,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = {  static void siu_dai_start(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);  	/* Turn on SIU clock */ -	pm_runtime_get_sync(siu_i2s_dai.dev); +	pm_runtime_get_sync(port_info->pcm->card->dev);  	/* Issue software reset to siu */  	siu_write32(base + SIU_SRCTL, 0); @@ -148,21 +151,21 @@ static void siu_dai_start(struct siu_port *port_info)  	siu_write32(base + SIU_SBDVCB, port_info->capture.volume);  } -static void siu_dai_stop(void) +static void siu_dai_stop(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	/* SIU software reset */  	siu_write32(base + SIU_SRCTL, 0);  	/* Turn off SIU clock */ -	pm_runtime_put_sync(siu_i2s_dai.dev); +	pm_runtime_put_sync(port_info->pcm->card->dev);  }  static void siu_dai_spbAselect(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct siu_firmware *fw = &info->fw;  	u32 *ydef = fw->yram0;  	u32 idx; @@ -187,7 +190,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info)  static void siu_dai_spbBselect(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct siu_firmware *fw = &info->fw;  	u32 *ydef = fw->yram0;  	u32 idx; @@ -207,7 +210,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info)  static void siu_dai_open(struct siu_stream *siu_stream)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	u32 srctl, ifctl; @@ -238,7 +241,7 @@ static void siu_dai_open(struct siu_stream *siu_stream)   */  static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	u32 dpak; @@ -258,7 +261,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)  static int siu_dai_spbstart(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_firmware *fw = &info->fw;  	u32 *ydef = fw->yram0; @@ -323,7 +326,7 @@ static int siu_dai_spbstart(struct siu_port *port_info)  static void siu_dai_spbstop(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	siu_write32(base + SIU_SBACTIV, 0); @@ -402,7 +405,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,  {  	struct siu_port *port_info = snd_kcontrol_chip(kctrl);  	struct device *dev = port_info->pcm->card->dev; -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	u32 new_vol;  	u32 cur_vol; @@ -510,7 +513,7 @@ void siu_free_port(struct siu_port *port_info)  static int siu_dai_startup(struct snd_pcm_substream *substream,  			   struct snd_soc_dai *dai)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = snd_soc_dai_get_drvdata(dai);  	struct snd_pcm_runtime *rt = substream->runtime;  	struct siu_port	*port_info = siu_port_info(substream);  	int ret; @@ -532,7 +535,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream,  static void siu_dai_shutdown(struct snd_pcm_substream *substream,  			     struct snd_soc_dai *dai)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = snd_soc_dai_get_drvdata(dai);  	struct siu_port	*port_info = siu_port_info(substream);  	dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, @@ -548,7 +551,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,  		/* during stmread or stmwrite ? */  		BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);  		siu_dai_spbstop(port_info); -		siu_dai_stop(); +		siu_dai_stop(port_info);  	}  } @@ -556,7 +559,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,  static int siu_dai_prepare(struct snd_pcm_substream *substream,  			   struct snd_soc_dai *dai)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = snd_soc_dai_get_drvdata(dai);  	struct snd_pcm_runtime *rt = substream->runtime;  	struct siu_port *port_info = siu_port_info(substream);  	struct siu_stream *siu_stream; @@ -605,7 +608,7 @@ fail:  static int siu_dai_set_fmt(struct snd_soc_dai *dai,  			   unsigned int fmt)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = snd_soc_dai_get_drvdata(dai);  	u32 __iomem *base = info->reg;  	u32 ifctl; @@ -671,11 +674,11 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,  		return -EINVAL;  	} -	siu_clk = clk_get(siu_i2s_dai.dev, siu_name); +	siu_clk = clk_get(dai->dev, siu_name);  	if (IS_ERR(siu_clk))  		return PTR_ERR(siu_clk); -	parent_clk = clk_get(siu_i2s_dai.dev, parent_name); +	parent_clk = clk_get(dai->dev, parent_name);  	if (!IS_ERR(parent_clk)) {  		ret = clk_set_parent(siu_clk, parent_clk);  		if (!ret) @@ -696,9 +699,8 @@ static struct snd_soc_dai_ops siu_dai_ops = {  	.set_fmt	= siu_dai_set_fmt,  }; -struct snd_soc_dai siu_i2s_dai = { -	.name = "sh-siu", -	.id = 0, +static struct snd_soc_dai_driver siu_i2s_dai = { +	.name	= "sui-i2s-dai",  	.playback = {  		.channels_min = 2,  		.channels_max = 2, @@ -713,7 +715,6 @@ struct snd_soc_dai siu_i2s_dai = {  	 },  	.ops = &siu_dai_ops,  }; -EXPORT_SYMBOL_GPL(siu_i2s_dai);  static int __devinit siu_probe(struct platform_device *pdev)  { @@ -725,6 +726,7 @@ static int __devinit siu_probe(struct platform_device *pdev)  	info = kmalloc(sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; +	siu_i2s_data = info;  	ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);  	if (ret) @@ -767,14 +769,14 @@ static int __devinit siu_probe(struct platform_device *pdev)  	if (!info->reg)  		goto emapreg; -	siu_i2s_dai.dev = &pdev->dev; -	siu_i2s_dai.private_data = info; +	dev_set_drvdata(&pdev->dev, info); -	ret = snd_soc_register_dais(&siu_i2s_dai, 1); +	/* register using ARRAY version so we can keep dai name */ +	ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1);  	if (ret < 0)  		goto edaiinit; -	ret = snd_soc_register_platform(&siu_platform); +	ret = snd_soc_register_platform(&pdev->dev, &siu_platform);  	if (ret < 0)  		goto esocregp; @@ -783,7 +785,7 @@ static int __devinit siu_probe(struct platform_device *pdev)  	return ret;  esocregp: -	snd_soc_unregister_dais(&siu_i2s_dai, 1); +	snd_soc_unregister_dai(&pdev->dev);  edaiinit:  	iounmap(info->reg);  emapreg: @@ -804,13 +806,13 @@ ereqfw:  static int __devexit siu_remove(struct platform_device *pdev)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = dev_get_drvdata(&pdev->dev);  	struct resource *res;  	pm_runtime_disable(&pdev->dev); -	snd_soc_unregister_platform(&siu_platform); -	snd_soc_unregister_dais(&siu_i2s_dai, 1); +	snd_soc_unregister_platform(&pdev->dev); +	snd_soc_unregister_dai(&pdev->dev);  	iounmap(info->reg);  	iounmap(info->yram); @@ -826,7 +828,7 @@ static int __devexit siu_remove(struct platform_device *pdev)  static struct platform_driver siu_driver = {  	.driver 	= { -		.name	= "sh_siu", +		.name	= "siu-pcm-audio",  	},  	.probe		= siu_probe,  	.remove		= __devexit_p(siu_remove), diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 36170be15aa7..440476993325 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -48,7 +48,7 @@ struct siu_port *siu_ports[SIU_PORT_NUM];  /* transfersize is number of u32 dma transfers per period */  static int siu_pcm_stmwrite_stop(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_stream *siu_stream = &port_info->playback;  	u32 stfifo; @@ -114,7 +114,7 @@ static void siu_dma_tx_complete(void *arg)  static int siu_pcm_wr_set(struct siu_port *port_info,  			  dma_addr_t buff, u32 size)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_stream *siu_stream = &port_info->playback;  	struct snd_pcm_substream *substream = siu_stream->substream; @@ -161,7 +161,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,  static int siu_pcm_rd_set(struct siu_port *port_info,  			  dma_addr_t buff, size_t size)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_stream *siu_stream = &port_info->capture;  	struct snd_pcm_substream *substream = siu_stream->substream; @@ -270,7 +270,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info)  static int siu_pcm_stmread_stop(struct siu_port *port_info)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_stream *siu_stream = &port_info->capture;  	struct device *dev = siu_stream->substream->pcm->card->dev; @@ -294,7 +294,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info)  static int siu_pcm_hw_params(struct snd_pcm_substream *ss,  			     struct snd_pcm_hw_params *hw_params)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct device *dev = ss->pcm->card->dev;  	int ret; @@ -309,7 +309,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss,  static int siu_pcm_hw_free(struct snd_pcm_substream *ss)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct siu_port	*port_info = siu_port_info(ss);  	struct device *dev = ss->pcm->card->dev;  	struct siu_stream *siu_stream; @@ -340,11 +340,12 @@ static bool filter(struct dma_chan *chan, void *slave)  static int siu_pcm_open(struct snd_pcm_substream *ss)  {  	/* Playback / Capture */ -	struct siu_info *info = siu_i2s_dai.private_data; +	struct snd_soc_pcm_runtime *rtd = ss->private_data; +	struct siu_platform *pdata = snd_soc_platform_get_drvdata(rtd->platform); +	struct siu_info *info = siu_i2s_data;  	struct siu_port *port_info = siu_port_info(ss);  	struct siu_stream *siu_stream;  	u32 port = info->port_id; -	struct siu_platform *pdata = siu_i2s_dai.dev->platform_data;  	struct device *dev = ss->pcm->card->dev;  	dma_cap_mask_t mask;  	struct sh_dmae_slave *param; @@ -381,7 +382,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss)  static int siu_pcm_close(struct snd_pcm_substream *ss)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct device *dev = ss->pcm->card->dev;  	struct siu_port *port_info = siu_port_info(ss);  	struct siu_stream *siu_stream; @@ -403,7 +404,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss)  static int siu_pcm_prepare(struct snd_pcm_substream *ss)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct siu_port *port_info = siu_port_info(ss);  	struct device *dev = ss->pcm->card->dev;  	struct snd_pcm_runtime 	*rt = ss->runtime; @@ -449,7 +450,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss)  static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)  { -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct device *dev = ss->pcm->card->dev;  	struct siu_port *port_info = siu_port_info(ss);  	int ret; @@ -492,7 +493,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)  static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)  {  	struct device *dev = ss->pcm->card->dev; -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	u32 __iomem *base = info->reg;  	struct siu_port *port_info = siu_port_info(ss);  	struct snd_pcm_runtime *rt = ss->runtime; @@ -528,7 +529,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  		       struct snd_pcm *pcm)  {  	/* card->dev == socdev->dev, see snd_soc_new_pcms() */ -	struct siu_info *info = siu_i2s_dai.private_data; +	struct siu_info *info = siu_i2s_data;  	struct platform_device *pdev = to_platform_device(card->dev);  	int ret;  	int i; @@ -605,9 +606,8 @@ static struct snd_pcm_ops siu_pcm_ops = {  	.pointer	= siu_pcm_pointer_dma,  }; -struct snd_soc_platform siu_platform = { -	.name		= "siu-audio", -	.pcm_ops 	= &siu_pcm_ops, +struct snd_soc_platform_driver siu_platform = { +	.ops			= &siu_pcm_ops,  	.pcm_new	= siu_pcm_new,  	.pcm_free	= siu_pcm_free,  }; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index b378096cadb1..40bbdf1591dc 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -92,8 +92,7 @@ struct ssi_priv {  static int ssi_startup(struct snd_pcm_substream *substream,  		       struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; +	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];  	if (ssi->inuse) {  		pr_debug("ssi: already in use!\n");  		return -EBUSY; @@ -105,8 +104,7 @@ static int ssi_startup(struct snd_pcm_substream *substream,  static void ssi_shutdown(struct snd_pcm_substream *substream,  			 struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; +	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];  	ssi->inuse = 0;  } @@ -114,8 +112,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream,  static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,  		       struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; +	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];  	switch (cmd) {  	case SNDRV_PCM_TRIGGER_START: @@ -135,8 +132,7 @@ static int ssi_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 ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; +	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];  	unsigned long ssicr = SSIREG(SSICR);  	unsigned int bits, channels, swl, recv, i; @@ -346,10 +342,9 @@ static struct snd_soc_dai_ops ssi_dai_ops = {  	.set_fmt	= ssi_set_fmt,  }; -struct snd_soc_dai sh4_ssi_dai[] = { +struct snd_soc_dai_driver sh4_ssi_dai[] = {  { -	.name			= "SSI0", -	.id			= 0, +	.name			= "ssi-dai.0",  	.playback = {  		.rates		= SSI_RATES,  		.formats	= SSI_FMTS, @@ -366,8 +361,7 @@ struct snd_soc_dai sh4_ssi_dai[] = {  },  #ifdef CONFIG_CPU_SUBTYPE_SH7760  { -	.name			= "SSI1", -	.id			= 1, +	.name			= "ssi-dai.1",  	.playback = {  		.rates		= SSI_RATES,  		.formats	= SSI_FMTS, @@ -384,19 +378,40 @@ struct snd_soc_dai sh4_ssi_dai[] = {  },  #endif  }; -EXPORT_SYMBOL_GPL(sh4_ssi_dai); -static int __init sh4_ssi_init(void) +static int __devinit sh4_soc_dai_probe(struct platform_device *pdev) +{ +	return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai, +			ARRAY_SIZE(sh4_ssi_dai)); +} + +static int __devexit sh4_soc_dai_remove(struct platform_device *pdev) +{ +	snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); +	return 0; +} + +static struct platform_driver sh4_ssi_driver = { +	.driver = { +			.name = "sh4-ssi-dai", +			.owner = THIS_MODULE, +	}, + +	.probe = sh4_soc_dai_probe, +	.remove = __devexit_p(sh4_soc_dai_remove), +}; + +static int __init snd_sh4_ssi_init(void)  { -	return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); +	return platform_driver_register(&sh4_ssi_driver);  } -module_init(sh4_ssi_init); +module_init(snd_sh4_ssi_init); -static void __exit sh4_ssi_exit(void) +static void __exit snd_sh4_ssi_exit(void)  { -	snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); +	platform_driver_unregister(&sh4_ssi_driver);  } -module_exit(sh4_ssi_exit); +module_exit(snd_sh4_ssi_exit);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 472af38188c1..b856177ea281 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -19,7 +19,7 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,  				     unsigned int reg)  {  	u16 *cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -1;  	return cache[reg];  } @@ -31,12 +31,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,  	u8 data[2];  	int ret; -	BUG_ON(codec->volatile_register); +	BUG_ON(codec->driver->volatile_register);  	data[0] = (reg << 4) | ((value >> 8) & 0x000f);  	data[1] = value & 0x00ff; -	if (reg < codec->reg_cache_size) +	if (reg < codec->driver->reg_cache_size)  		cache[reg] = value;  	if (codec->cache_only) { @@ -89,7 +89,7 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,  				     unsigned int reg)  {  	u16 *cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -1;  	return cache[reg];  } @@ -101,12 +101,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,  	u8 data[2];  	int ret; -	BUG_ON(codec->volatile_register); +	BUG_ON(codec->driver->volatile_register);  	data[0] = (reg << 1) | ((value >> 8) & 0x0001);  	data[1] = value & 0x00ff; -	if (reg < codec->reg_cache_size) +	if (reg < codec->driver->reg_cache_size)  		cache[reg] = value;  	if (codec->cache_only) { @@ -161,13 +161,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,  	u8 *cache = codec->reg_cache;  	u8 data[2]; -	BUG_ON(codec->volatile_register); +	BUG_ON(codec->driver->volatile_register);  	reg &= 0xff;  	data[0] = reg;  	data[1] = value & 0xff; -	if (reg < codec->reg_cache_size) +	if (reg < codec->driver->reg_cache_size)  		cache[reg] = value;  	if (codec->cache_only) { @@ -188,7 +188,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,  {  	u8 *cache = codec->reg_cache;  	reg &= 0xff; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -1;  	return cache[reg];  } @@ -224,7 +224,7 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,  {  	u16 *cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size || +	if (reg >= codec->driver->reg_cache_size ||  	    snd_soc_codec_volatile_register(codec, reg)) {  		if (codec->cache_only)  			return -EINVAL; @@ -343,7 +343,7 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,  	u16 *cache = codec->reg_cache;  	reg &= 0xff; -	if (reg >= codec->reg_cache_size) +	if (reg >= codec->driver->reg_cache_size)  		return -1;  	return cache[reg];  } @@ -355,14 +355,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,  	u8 data[3];  	int ret; -	BUG_ON(codec->volatile_register); +	BUG_ON(codec->driver->volatile_register);  	data[0] = (reg >> 8) & 0xff;  	data[1] = reg & 0xff;  	data[2] = value;  	reg &= 0xff; -	if (reg < codec->reg_cache_size) +	if (reg < codec->driver->reg_cache_size)  		cache[reg] = value;  	if (codec->cache_only) { @@ -451,7 +451,7 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,  {  	u16 *cache = codec->reg_cache; -	if (reg >= codec->reg_cache_size || +	if (reg >= codec->driver->reg_cache_size ||  	    snd_soc_codec_volatile_register(codec, reg)) {  		if (codec->cache_only)  			return -EINVAL; @@ -474,7 +474,7 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,  	data[2] = (value >> 8) & 0xff;  	data[3] = value & 0xff; -	if (reg < codec->reg_cache_size) +	if (reg < codec->driver->reg_cache_size)  		cache[reg] = value;  	if (codec->cache_only) { @@ -571,8 +571,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,  		return -EINVAL;  	} -	codec->write = io_types[i].write; -	codec->read = io_types[i].read; +	codec->driver->write = io_types[i].write; +	codec->driver->read = io_types[i].read;  	switch (control) {  	case SND_SOC_CUSTOM: @@ -584,11 +584,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,  #endif  		if (io_types[i].i2c_read)  			codec->hw_read = io_types[i].i2c_read; + +		codec->control_data = container_of(codec->dev, +						   struct i2c_client, +						   dev);  		break;  	case SND_SOC_SPI:  		if (io_types[i].spi_write)  			codec->hw_write = io_types[i].spi_write; + +		codec->control_data = container_of(codec->dev, +						   struct spi_device, +						   dev);  		break;  	} diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 5299932db0b6..a004876a39a9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3,6 +3,8 @@   *   * Copyright 2005 Wolfson Microelectronics PLC.   * Copyright 2005 Openedhand Ltd. + * Copyright (C) 2010 Slimlogic Ltd. + * Copyright (C) 2010 Texas Instruments Inc.   *   * Author: Liam Girdwood <lrg@slimlogic.co.uk>   *         with code, comments and ideas from :- @@ -37,6 +39,8 @@  #include <sound/soc-dapm.h>  #include <sound/initval.h> +#define NAME_SIZE	32 +  static DEFINE_MUTEX(pcm_mutex);  static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); @@ -52,6 +56,7 @@ static LIST_HEAD(codec_list);  static int snd_soc_register_card(struct snd_soc_card *card);  static int snd_soc_unregister_card(struct snd_soc_card *card); +static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);  /*   * This is a timeout to do a DAPM powerdown after a stream is closed(). @@ -86,30 +91,30 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)  {  	int ret, i, step = 1, count = 0; -	if (!codec->reg_cache_size) +	if (!codec->driver->reg_cache_size)  		return 0; -	if (codec->reg_cache_step) -		step = codec->reg_cache_step; +	if (codec->driver->reg_cache_step) +		step = codec->driver->reg_cache_step;  	count += sprintf(buf, "%s registers\n", codec->name); -	for (i = 0; i < codec->reg_cache_size; i += step) { -		if (codec->readable_register && !codec->readable_register(i)) +	for (i = 0; i < codec->driver->reg_cache_size; i += step) { +		if (codec->driver->readable_register && !codec->driver->readable_register(i))  			continue;  		count += sprintf(buf + count, "%2x: ", i);  		if (count >= PAGE_SIZE - 1)  			break; -		if (codec->display_register) { -			count += codec->display_register(codec, buf + count, +		if (codec->driver->display_register) { +			count += codec->driver->display_register(codec, buf + count,  							 PAGE_SIZE - count, i);  		} else {  			/* If the read fails it's almost certainly due to  			 * the register being volatile and the device being  			 * powered off.  			 */ -			ret = codec->read(codec, i); +			ret = codec->driver->read(codec, i);  			if (ret >= 0)  				count += snprintf(buf + count,  						  PAGE_SIZE - count, @@ -137,8 +142,10 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)  static ssize_t codec_reg_show(struct device *dev,  	struct device_attribute *attr, char *buf)  { -	struct snd_soc_device *devdata = dev_get_drvdata(dev); -	return soc_codec_reg_show(devdata->card->codec, buf); +	struct snd_soc_pcm_runtime *rtd = +			container_of(dev, struct snd_soc_pcm_runtime, dev); + +	return soc_codec_reg_show(rtd->codec, buf);  }  static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); @@ -146,20 +153,20 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);  static ssize_t pmdown_time_show(struct device *dev,  				struct device_attribute *attr, char *buf)  { -	struct snd_soc_device *socdev = dev_get_drvdata(dev); -	struct snd_soc_card *card = socdev->card; +	struct snd_soc_pcm_runtime *rtd = +			container_of(dev, struct snd_soc_pcm_runtime, dev); -	return sprintf(buf, "%ld\n", card->pmdown_time); +	return sprintf(buf, "%ld\n", rtd->pmdown_time);  }  static ssize_t pmdown_time_set(struct device *dev,  			       struct device_attribute *attr,  			       const char *buf, size_t count)  { -	struct snd_soc_device *socdev = dev_get_drvdata(dev); -	struct snd_soc_card *card = socdev->card; +	struct snd_soc_pcm_runtime *rtd = +			container_of(dev, struct snd_soc_pcm_runtime, dev); -	strict_strtol(buf, 10, &card->pmdown_time); +	strict_strtol(buf, 10, &rtd->pmdown_time);  	return count;  } @@ -203,19 +210,19 @@ static ssize_t codec_reg_write_file(struct file *file,  		return -EFAULT;  	buf[buf_size] = 0; -	if (codec->reg_cache_step) -		step = codec->reg_cache_step; +	if (codec->driver->reg_cache_step) +		step = codec->driver->reg_cache_step;  	while (*start == ' ')  		start++;  	reg = simple_strtoul(start, &start, 16); -	if ((reg >= codec->reg_cache_size) || (reg % step)) +	if ((reg >= codec->driver->reg_cache_size) || (reg % step))  		return -EINVAL;  	while (*start == ' ')  		start++;  	if (strict_strtoul(start, 16, &value))  		return -EINVAL; -	codec->write(codec, reg, value); +	codec->driver->write(codec, reg, value);  	return buf_size;  } @@ -305,7 +312,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)  	codec->ac97->dev.release = soc_ac97_device_release;  	dev_set_name(&codec->ac97->dev, "%d-%d:%s", -		     codec->card->number, 0, codec->name); +		     codec->card->snd_card->number, 0, codec->name);  	err = device_register(&codec->ac97->dev);  	if (err < 0) {  		snd_printk(KERN_ERR "Can't register ac97 bus\n"); @@ -319,24 +326,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)  static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	int ret; -	if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || -	    machine->symmetric_rates) { -		dev_dbg(card->dev, "Symmetry forces %dHz rate\n", -			machine->rate); +	if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates || +			rtd->dai_link->symmetric_rates) { +		dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", +				rtd->rate);  		ret = snd_pcm_hw_constraint_minmax(substream->runtime,  						   SNDRV_PCM_HW_PARAM_RATE, -						   machine->rate, -						   machine->rate); +						   rtd->rate, +						   rtd->rate);  		if (ret < 0) { -			dev_err(card->dev, +			dev_err(&rtd->dev,  				"Unable to apply rate symmetry constraint: %d\n", ret);  			return ret;  		} @@ -353,20 +357,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)  static int soc_pcm_open(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card = socdev->card;  	struct snd_pcm_runtime *runtime = substream->runtime; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; +	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;  	int ret = 0;  	mutex_lock(&pcm_mutex);  	/* startup the audio subsystem */ -	if (cpu_dai->ops->startup) { -		ret = cpu_dai->ops->startup(substream, cpu_dai); +	if (cpu_dai->driver->ops->startup) { +		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);  		if (ret < 0) {  			printk(KERN_ERR "asoc: can't open interface %s\n",  				cpu_dai->name); @@ -374,16 +377,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  		}  	} -	if (platform->pcm_ops->open) { -		ret = platform->pcm_ops->open(substream); +	if (platform->driver->ops->open) { +		ret = platform->driver->ops->open(substream);  		if (ret < 0) {  			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);  			goto platform_err;  		}  	} -	if (codec_dai->ops->startup) { -		ret = codec_dai->ops->startup(substream, codec_dai); +	if (codec_dai->driver->ops->startup) { +		ret = codec_dai->driver->ops->startup(substream, codec_dai);  		if (ret < 0) {  			printk(KERN_ERR "asoc: can't open codec %s\n",  				codec_dai->name); @@ -391,10 +394,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  		}  	} -	if (machine->ops && machine->ops->startup) { -		ret = machine->ops->startup(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { +		ret = rtd->dai_link->ops->startup(substream);  		if (ret < 0) { -			printk(KERN_ERR "asoc: %s startup failed\n", machine->name); +			printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);  			goto machine_err;  		}  	} @@ -402,50 +405,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  	/* Check that the codec and cpu DAI's are compatible */  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {  		runtime->hw.rate_min = -			max(codec_dai->playback.rate_min, -			    cpu_dai->playback.rate_min); +			max(codec_dai_drv->playback.rate_min, +			    cpu_dai_drv->playback.rate_min);  		runtime->hw.rate_max = -			min(codec_dai->playback.rate_max, -			    cpu_dai->playback.rate_max); +			min(codec_dai_drv->playback.rate_max, +			    cpu_dai_drv->playback.rate_max);  		runtime->hw.channels_min = -			max(codec_dai->playback.channels_min, -				cpu_dai->playback.channels_min); +			max(codec_dai_drv->playback.channels_min, +				cpu_dai_drv->playback.channels_min);  		runtime->hw.channels_max = -			min(codec_dai->playback.channels_max, -				cpu_dai->playback.channels_max); +			min(codec_dai_drv->playback.channels_max, +				cpu_dai_drv->playback.channels_max);  		runtime->hw.formats = -			codec_dai->playback.formats & cpu_dai->playback.formats; +			codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;  		runtime->hw.rates = -			codec_dai->playback.rates & cpu_dai->playback.rates; -		if (codec_dai->playback.rates +			codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; +		if (codec_dai_drv->playback.rates  			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) -			runtime->hw.rates |= cpu_dai->playback.rates; -		if (cpu_dai->playback.rates +			runtime->hw.rates |= cpu_dai_drv->playback.rates; +		if (cpu_dai_drv->playback.rates  			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) -			runtime->hw.rates |= codec_dai->playback.rates; +			runtime->hw.rates |= codec_dai_drv->playback.rates;  	} else {  		runtime->hw.rate_min = -			max(codec_dai->capture.rate_min, -			    cpu_dai->capture.rate_min); +			max(codec_dai_drv->capture.rate_min, +			    cpu_dai_drv->capture.rate_min);  		runtime->hw.rate_max = -			min(codec_dai->capture.rate_max, -			    cpu_dai->capture.rate_max); +			min(codec_dai_drv->capture.rate_max, +			    cpu_dai_drv->capture.rate_max);  		runtime->hw.channels_min = -			max(codec_dai->capture.channels_min, -				cpu_dai->capture.channels_min); +			max(codec_dai_drv->capture.channels_min, +				cpu_dai_drv->capture.channels_min);  		runtime->hw.channels_max = -			min(codec_dai->capture.channels_max, -				cpu_dai->capture.channels_max); +			min(codec_dai_drv->capture.channels_max, +				cpu_dai_drv->capture.channels_max);  		runtime->hw.formats = -			codec_dai->capture.formats & cpu_dai->capture.formats; +			codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;  		runtime->hw.rates = -			codec_dai->capture.rates & cpu_dai->capture.rates; -		if (codec_dai->capture.rates +			codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; +		if (codec_dai_drv->capture.rates  			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) -			runtime->hw.rates |= cpu_dai->capture.rates; -		if (cpu_dai->capture.rates +			runtime->hw.rates |= cpu_dai_drv->capture.rates; +		if (cpu_dai_drv->capture.rates  			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) -			runtime->hw.rates |= codec_dai->capture.rates; +			runtime->hw.rates |= codec_dai_drv->capture.rates;  	}  	snd_pcm_limit_hw_rates(runtime); @@ -461,7 +464,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  	}  	if (!runtime->hw.channels_min || !runtime->hw.channels_max) {  		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", -			codec_dai->name, cpu_dai->name); +				codec_dai->name, cpu_dai->name);  		goto config_err;  	} @@ -472,7 +475,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  			goto config_err;  	} -	pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); +	pr_debug("asoc: %s <-> %s info:\n", +			codec_dai->name, cpu_dai->name);  	pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);  	pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,  		 runtime->hw.channels_max); @@ -480,33 +484,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)  		 runtime->hw.rate_max);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -		cpu_dai->playback.active++; -		codec_dai->playback.active++; +		cpu_dai->playback_active++; +		codec_dai->playback_active++;  	} else { -		cpu_dai->capture.active++; -		codec_dai->capture.active++; +		cpu_dai->capture_active++; +		codec_dai->capture_active++;  	}  	cpu_dai->active++;  	codec_dai->active++; -	card->codec->active++; +	rtd->codec->active++;  	mutex_unlock(&pcm_mutex);  	return 0;  config_err: -	if (machine->ops && machine->ops->shutdown) -		machine->ops->shutdown(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) +		rtd->dai_link->ops->shutdown(substream);  machine_err: -	if (codec_dai->ops->shutdown) -		codec_dai->ops->shutdown(substream, codec_dai); +	if (codec_dai->driver->ops->shutdown) +		codec_dai->driver->ops->shutdown(substream, codec_dai);  codec_dai_err: -	if (platform->pcm_ops->close) -		platform->pcm_ops->close(substream); +	if (platform->driver->ops->close) +		platform->driver->ops->close(substream);  platform_err: -	if (cpu_dai->ops->shutdown) -		cpu_dai->ops->shutdown(substream, cpu_dai); +	if (cpu_dai->driver->ops->shutdown) +		cpu_dai->driver->ops->shutdown(substream, cpu_dai);  out:  	mutex_unlock(&pcm_mutex);  	return ret; @@ -519,29 +523,25 @@ out:   */  static void close_delayed_work(struct work_struct *work)  { -	struct snd_soc_card *card = container_of(work, struct snd_soc_card, -						 delayed_work.work); -	struct snd_soc_codec *codec = card->codec; -	struct snd_soc_dai *codec_dai; -	int i; +	struct snd_soc_pcm_runtime *rtd = +			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	mutex_lock(&pcm_mutex); -	for (i = 0; i < codec->num_dai; i++) { -		codec_dai = &codec->dai[i]; - -		pr_debug("pop wq checking: %s status: %s waiting: %s\n", -			 codec_dai->playback.stream_name, -			 codec_dai->playback.active ? "active" : "inactive", -			 codec_dai->pop_wait ? "yes" : "no"); - -		/* are we waiting on this codec DAI stream */ -		if (codec_dai->pop_wait == 1) { -			codec_dai->pop_wait = 0; -			snd_soc_dapm_stream_event(codec, -				codec_dai->playback.stream_name, -				SND_SOC_DAPM_STREAM_STOP); -		} + +	pr_debug("pop wq checking: %s status: %s waiting: %s\n", +		 codec_dai->driver->playback.stream_name, +		 codec_dai->playback_active ? "active" : "inactive", +		 codec_dai->pop_wait ? "yes" : "no"); + +	/* are we waiting on this codec DAI stream */ +	if (codec_dai->pop_wait == 1) { +		codec_dai->pop_wait = 0; +		snd_soc_dapm_stream_event(rtd, +			codec_dai->driver->playback.stream_name, +			SND_SOC_DAPM_STREAM_STOP);  	} +  	mutex_unlock(&pcm_mutex);  } @@ -553,22 +553,19 @@ static void close_delayed_work(struct work_struct *work)  static int soc_codec_close(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; -	struct snd_soc_codec *codec = card->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_codec *codec = rtd->codec;  	mutex_lock(&pcm_mutex);  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -		cpu_dai->playback.active--; -		codec_dai->playback.active--; +		cpu_dai->playback_active--; +		codec_dai->playback_active--;  	} else { -		cpu_dai->capture.active--; -		codec_dai->capture.active--; +		cpu_dai->capture_active--; +		codec_dai->capture_active--;  	}  	cpu_dai->active--; @@ -581,27 +578,28 @@ 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->driver->ops->shutdown) +		cpu_dai->driver->ops->shutdown(substream, cpu_dai); -	if (codec_dai->ops->shutdown) -		codec_dai->ops->shutdown(substream, codec_dai); +	if (codec_dai->driver->ops->shutdown) +		codec_dai->driver->ops->shutdown(substream, codec_dai); -	if (machine->ops && machine->ops->shutdown) -		machine->ops->shutdown(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) +		rtd->dai_link->ops->shutdown(substream); -	if (platform->pcm_ops->close) -		platform->pcm_ops->close(substream); +	if (platform->driver->ops->close) +		platform->driver->ops->close(substream); +	cpu_dai->runtime = NULL;  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {  		/* start delayed pop wq here for playback streams */  		codec_dai->pop_wait = 1; -		schedule_delayed_work(&card->delayed_work, -			msecs_to_jiffies(card->pmdown_time)); +		schedule_delayed_work(&rtd->delayed_work, +			msecs_to_jiffies(rtd->pmdown_time));  	} else {  		/* capture streams can be powered down now */ -		snd_soc_dapm_stream_event(codec, -			codec_dai->capture.stream_name, +		snd_soc_dapm_stream_event(rtd, +			codec_dai->driver->capture.stream_name,  			SND_SOC_DAPM_STREAM_STOP);  	} @@ -617,43 +615,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream)  static int soc_pcm_prepare(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; -	struct snd_soc_codec *codec = card->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	int ret = 0;  	mutex_lock(&pcm_mutex); -	if (machine->ops && machine->ops->prepare) { -		ret = machine->ops->prepare(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { +		ret = rtd->dai_link->ops->prepare(substream);  		if (ret < 0) {  			printk(KERN_ERR "asoc: machine prepare error\n");  			goto out;  		}  	} -	if (platform->pcm_ops->prepare) { -		ret = platform->pcm_ops->prepare(substream); +	if (platform->driver->ops->prepare) { +		ret = platform->driver->ops->prepare(substream);  		if (ret < 0) {  			printk(KERN_ERR "asoc: platform prepare error\n");  			goto out;  		}  	} -	if (codec_dai->ops->prepare) { -		ret = codec_dai->ops->prepare(substream, codec_dai); +	if (codec_dai->driver->ops->prepare) { +		ret = codec_dai->driver->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->driver->ops->prepare) { +		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);  		if (ret < 0) {  			printk(KERN_ERR "asoc: cpu DAI prepare error\n");  			goto out; @@ -664,16 +658,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&  	    codec_dai->pop_wait) {  		codec_dai->pop_wait = 0; -		cancel_delayed_work(&card->delayed_work); +		cancel_delayed_work(&rtd->delayed_work);  	}  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -		snd_soc_dapm_stream_event(codec, -					  codec_dai->playback.stream_name, +		snd_soc_dapm_stream_event(rtd, +					  codec_dai->driver->playback.stream_name,  					  SND_SOC_DAPM_STREAM_START);  	else -		snd_soc_dapm_stream_event(codec, -					  codec_dai->capture.stream_name, +		snd_soc_dapm_stream_event(rtd, +					  codec_dai->driver->capture.stream_name,  					  SND_SOC_DAPM_STREAM_START);  	snd_soc_dai_digital_mute(codec_dai, 0); @@ -692,26 +686,23 @@ static int soc_pcm_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_device *socdev = rtd->socdev; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	int ret = 0;  	mutex_lock(&pcm_mutex); -	if (machine->ops && machine->ops->hw_params) { -		ret = machine->ops->hw_params(substream, params); +	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { +		ret = rtd->dai_link->ops->hw_params(substream, params);  		if (ret < 0) {  			printk(KERN_ERR "asoc: machine hw_params failed\n");  			goto out;  		}  	} -	if (codec_dai->ops->hw_params) { -		ret = codec_dai->ops->hw_params(substream, params, codec_dai); +	if (codec_dai->driver->ops->hw_params) { +		ret = codec_dai->driver->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); @@ -719,8 +710,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->driver->ops->hw_params) { +		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);  		if (ret < 0) {  			printk(KERN_ERR "asoc: interface %s hw params failed\n",  				cpu_dai->name); @@ -728,8 +719,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,  		}  	} -	if (platform->pcm_ops->hw_params) { -		ret = platform->pcm_ops->hw_params(substream, params); +	if (platform->driver->ops->hw_params) { +		ret = platform->driver->ops->hw_params(substream, params);  		if (ret < 0) {  			printk(KERN_ERR "asoc: platform %s hw params failed\n",  				platform->name); @@ -737,23 +728,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,  		}  	} -	machine->rate = params_rate(params); +	rtd->rate = params_rate(params);  out:  	mutex_unlock(&pcm_mutex);  	return ret;  platform_err: -	if (cpu_dai->ops->hw_free) -		cpu_dai->ops->hw_free(substream, cpu_dai); +	if (cpu_dai->driver->ops->hw_free) +		cpu_dai->driver->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->driver->ops->hw_free) +		codec_dai->driver->ops->hw_free(substream, codec_dai);  codec_err: -	if (machine->ops && machine->ops->hw_free) -		machine->ops->hw_free(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) +		rtd->dai_link->ops->hw_free(substream);  	mutex_unlock(&pcm_mutex);  	return ret; @@ -765,13 +756,10 @@ codec_err:  static int soc_pcm_hw_free(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; -	struct snd_soc_codec *codec = card->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_codec *codec = rtd->codec;  	mutex_lock(&pcm_mutex); @@ -780,19 +768,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)  		snd_soc_dai_digital_mute(codec_dai, 1);  	/* free any machine hw params */ -	if (machine->ops && machine->ops->hw_free) -		machine->ops->hw_free(substream); +	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) +		rtd->dai_link->ops->hw_free(substream);  	/* free any DMA resources */ -	if (platform->pcm_ops->hw_free) -		platform->pcm_ops->hw_free(substream); +	if (platform->driver->ops->hw_free) +		platform->driver->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->driver->ops->hw_free) +		codec_dai->driver->ops->hw_free(substream, codec_dai); -	if (cpu_dai->ops->hw_free) -		cpu_dai->ops->hw_free(substream, cpu_dai); +	if (cpu_dai->driver->ops->hw_free) +		cpu_dai->driver->ops->hw_free(substream, cpu_dai);  	mutex_unlock(&pcm_mutex);  	return 0; @@ -801,28 +789,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)  static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card= socdev->card; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	int ret; -	if (codec_dai->ops->trigger) { -		ret = codec_dai->ops->trigger(substream, cmd, codec_dai); +	if (codec_dai->driver->ops->trigger) { +		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);  		if (ret < 0)  			return ret;  	} -	if (platform->pcm_ops->trigger) { -		ret = platform->pcm_ops->trigger(substream, cmd); +	if (platform->driver->ops->trigger) { +		ret = platform->driver->ops->trigger(substream, cmd);  		if (ret < 0)  			return ret;  	} -	if (cpu_dai->ops->trigger) { -		ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); +	if (cpu_dai->driver->ops->trigger) { +		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);  		if (ret < 0)  			return ret;  	} @@ -837,27 +822,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)  static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)  {  	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_device *socdev = rtd->socdev; -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai_link *machine = rtd->dai; -	struct snd_soc_dai *cpu_dai = machine->cpu_dai; -	struct snd_soc_dai *codec_dai = machine->codec_dai; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +	struct snd_soc_dai *codec_dai = rtd->codec_dai;  	struct snd_pcm_runtime *runtime = substream->runtime;  	snd_pcm_uframes_t offset = 0;  	snd_pcm_sframes_t delay = 0; -	if (platform->pcm_ops->pointer) -		offset = platform->pcm_ops->pointer(substream); +	if (platform->driver->ops->pointer) +		offset = platform->driver->ops->pointer(substream); -	if (cpu_dai->ops->delay) -		delay += cpu_dai->ops->delay(substream, cpu_dai); +	if (cpu_dai->driver->ops->delay) +		delay += cpu_dai->driver->ops->delay(substream, cpu_dai); -	if (codec_dai->ops->delay) -		delay += codec_dai->ops->delay(substream, codec_dai); +	if (codec_dai->driver->ops->delay) +		delay += codec_dai->driver->ops->delay(substream, codec_dai); -	if (platform->delay) -		delay += platform->delay(substream, codec_dai); +	if (platform->driver->delay) +		delay += platform->driver->delay(substream, codec_dai);  	runtime->delay = delay; @@ -880,104 +862,111 @@ static struct snd_pcm_ops soc_pcm_ops = {  static int soc_suspend(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_codec_device *codec_dev = socdev->codec_dev; -	struct snd_soc_codec *codec = card->codec; +	struct snd_soc_card *card = platform_get_drvdata(pdev);  	int i;  	/* If the initialization of this soc device failed, there is no codec  	 * associated with it. Just bail out in this case.  	 */ -	if (!codec) +	if (list_empty(&card->codec_dev_list))  		return 0;  	/* Due to the resume being scheduled into a workqueue we could  	* suspend before that's finished - wait for it to complete.  	 */ -	snd_power_lock(codec->card); -	snd_power_wait(codec->card, SNDRV_CTL_POWER_D0); -	snd_power_unlock(codec->card); +	snd_power_lock(card->snd_card); +	snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); +	snd_power_unlock(card->snd_card);  	/* we're going to block userspace touching us until resume completes */ -	snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); +	snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);  	/* mute any active DAC's */ -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *dai = card->dai_link[i].codec_dai; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *dai = card->rtd[i].codec_dai; +		struct snd_soc_dai_driver *drv = dai->driver; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (dai->ops->digital_mute && dai->playback.active) -			dai->ops->digital_mute(dai, 1); +		if (drv->ops->digital_mute && dai->playback_active) +			drv->ops->digital_mute(dai, 1);  	}  	/* suspend all pcms */ -	for (i = 0; i < card->num_links; i++) { -		if (card->dai_link[i].ignore_suspend) +	for (i = 0; i < card->num_rtd; i++) { +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		snd_pcm_suspend_all(card->dai_link[i].pcm); +		snd_pcm_suspend_all(card->rtd[i].pcm);  	}  	if (card->suspend_pre)  		card->suspend_pre(pdev, PMSG_SUSPEND); -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai  *cpu_dai = card->dai_link[i].cpu_dai; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; +		struct snd_soc_platform *platform = card->rtd[i].platform; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (cpu_dai->suspend && !cpu_dai->ac97_control) -			cpu_dai->suspend(cpu_dai); -		if (platform->suspend) -			platform->suspend(&card->dai_link[i]); +		if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) +			cpu_dai->driver->suspend(cpu_dai); +		if (platform->driver->suspend && !platform->suspended) { +			platform->driver->suspend(cpu_dai); +			platform->suspended = 1; +		}  	}  	/* close any waiting streams and save state */ -	run_delayed_work(&card->delayed_work); -	codec->suspend_bias_level = codec->bias_level; +	for (i = 0; i < card->num_rtd; i++) { +		run_delayed_work(&card->rtd[i].delayed_work); +		card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level; +	} -	for (i = 0; i < codec->num_dai; i++) { -		char *stream = codec->dai[i].playback.stream_name; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (stream != NULL) -			snd_soc_dapm_stream_event(codec, stream, +		if (driver->playback.stream_name != NULL) +			snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,  				SND_SOC_DAPM_STREAM_SUSPEND); -		stream = codec->dai[i].capture.stream_name; -		if (stream != NULL) -			snd_soc_dapm_stream_event(codec, stream, + +		if (driver->capture.stream_name != NULL) +			snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,  				SND_SOC_DAPM_STREAM_SUSPEND);  	} -	/* If there are paths active then the CODEC will be held with -	 * bias _ON and should not be suspended. */ -	if (codec_dev->suspend) { -		switch (codec->bias_level) { -		case SND_SOC_BIAS_STANDBY: -		case SND_SOC_BIAS_OFF: -			codec_dev->suspend(pdev, PMSG_SUSPEND); -			break; -		default: -			dev_dbg(socdev->dev, "CODEC is on over suspend\n"); -			break; +	/* suspend all CODECs */ +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_codec *codec = card->rtd[i].codec; +		/* If there are paths active then the CODEC will be held with +		 * bias _ON and should not be suspended. */ +		if (!codec->suspended && codec->driver->suspend) { +			switch (codec->bias_level) { +			case SND_SOC_BIAS_STANDBY: +			case SND_SOC_BIAS_OFF: +				codec->driver->suspend(codec, PMSG_SUSPEND); +				codec->suspended = 1; +				break; +			default: +				dev_dbg(codec->dev, "CODEC is on over suspend\n"); +				break; +			}  		}  	} -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (cpu_dai->suspend && cpu_dai->ac97_control) -			cpu_dai->suspend(cpu_dai); +		if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) +			cpu_dai->driver->suspend(cpu_dai);  	}  	if (card->suspend_post) @@ -991,127 +980,127 @@ static int soc_suspend(struct device *dev)   */  static void soc_resume_deferred(struct work_struct *work)  { -	struct snd_soc_card *card = container_of(work, -						 struct snd_soc_card, -						 deferred_resume_work); -	struct snd_soc_device *socdev = card->socdev; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_codec_device *codec_dev = socdev->codec_dev; -	struct snd_soc_codec *codec = card->codec; -	struct platform_device *pdev = to_platform_device(socdev->dev); +	struct snd_soc_card *card = +			container_of(work, struct snd_soc_card, deferred_resume_work); +	struct platform_device *pdev = to_platform_device(card->dev);  	int i;  	/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,  	 * so userspace apps are blocked from touching us  	 */ -	dev_dbg(socdev->dev, "starting resume work\n"); +	dev_dbg(card->dev, "starting resume work\n");  	/* Bring us up into D2 so that DAPM starts enabling things */ -	snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); +	snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);  	if (card->resume_pre)  		card->resume_pre(pdev); -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; +	/* resume AC97 DAIs */ +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (cpu_dai->resume && cpu_dai->ac97_control) -			cpu_dai->resume(cpu_dai); -	} - -	/* If the CODEC was idle over suspend then it will have been -	 * left with bias OFF or STANDBY and suspended so we must now -	 * resume.  Otherwise the suspend was suppressed. -	 */ -	if (codec_dev->resume) { -		switch (codec->bias_level) { -		case SND_SOC_BIAS_STANDBY: -		case SND_SOC_BIAS_OFF: -			codec_dev->resume(pdev); -			break; -		default: -			dev_dbg(socdev->dev, "CODEC was on over suspend\n"); -			break; +		if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) +			cpu_dai->driver->resume(cpu_dai); +	} + +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_codec *codec = card->rtd[i].codec; +		/* If the CODEC was idle over suspend then it will have been +		 * left with bias OFF or STANDBY and suspended so we must now +		 * resume.  Otherwise the suspend was suppressed. +		 */ +		if (codec->driver->resume && codec->suspended) { +			switch (codec->bias_level) { +			case SND_SOC_BIAS_STANDBY: +			case SND_SOC_BIAS_OFF: +				codec->driver->resume(codec); +				codec->suspended = 0; +				break; +			default: +				dev_dbg(codec->dev, "CODEC was on over suspend\n"); +				break; +			}  		}  	} -	for (i = 0; i < codec->num_dai; i++) { -		char *stream = codec->dai[i].playback.stream_name; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (stream != NULL) -			snd_soc_dapm_stream_event(codec, stream, +		if (driver->playback.stream_name != NULL) +			snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,  				SND_SOC_DAPM_STREAM_RESUME); -		stream = codec->dai[i].capture.stream_name; -		if (stream != NULL) -			snd_soc_dapm_stream_event(codec, stream, + +		if (driver->capture.stream_name != NULL) +			snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,  				SND_SOC_DAPM_STREAM_RESUME);  	}  	/* unmute any active DACs */ -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *dai = card->dai_link[i].codec_dai; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *dai = card->rtd[i].codec_dai; +		struct snd_soc_dai_driver *drv = dai->driver; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (dai->ops->digital_mute && dai->playback.active) -			dai->ops->digital_mute(dai, 0); +		if (drv->ops->digital_mute && dai->playback_active) +			drv->ops->digital_mute(dai, 0);  	} -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; +		struct snd_soc_platform *platform = card->rtd[i].platform; -		if (card->dai_link[i].ignore_suspend) +		if (card->rtd[i].dai_link->ignore_suspend)  			continue; -		if (cpu_dai->resume && !cpu_dai->ac97_control) -			cpu_dai->resume(cpu_dai); -		if (platform->resume) -			platform->resume(&card->dai_link[i]); +		if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) +			cpu_dai->driver->resume(cpu_dai); +		if (platform->driver->resume && platform->suspended) { +			platform->driver->resume(cpu_dai); +			platform->suspended = 0; +		}  	}  	if (card->resume_post)  		card->resume_post(pdev); -	dev_dbg(socdev->dev, "resume work completed\n"); +	dev_dbg(card->dev, "resume work completed\n");  	/* userspace can access us now we are back as we were before */ -	snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); +	snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);  }  /* powers up audio subsystem after a suspend */  static int soc_resume(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; - -	/* If the initialization of this soc device failed, there is no codec -	 * associated with it. Just bail out in this case. -	 */ -	if (!card->codec) -		return 0; +	struct snd_soc_card *card = platform_get_drvdata(pdev); +	int i;  	/* AC97 devices might have other drivers hanging off them so  	 * need to resume immediately.  Other drivers don't have that  	 * problem and may take a substantial amount of time to resume  	 * due to I/O costs and anti-pop so handle them out of line.  	 */ -	if (cpu_dai->ac97_control) { -		dev_dbg(socdev->dev, "Resuming AC97 immediately\n"); -		soc_resume_deferred(&card->deferred_resume_work); -	} else { -		dev_dbg(socdev->dev, "Scheduling resume work\n"); -		if (!schedule_work(&card->deferred_resume_work)) -			dev_err(socdev->dev, "resume work item may be lost\n"); +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; +		if (cpu_dai->driver->ac97_control) { +			dev_dbg(dev, "Resuming AC97 immediately\n"); +			soc_resume_deferred(&card->deferred_resume_work); +		} else { +			dev_dbg(dev, "Scheduling resume work\n"); +			if (!schedule_work(&card->deferred_resume_work)) +				dev_err(dev, "resume work item may be lost\n"); +		}  	}  	return 0; @@ -1124,198 +1113,429 @@ static int soc_resume(struct device *dev)  static struct snd_soc_dai_ops null_dai_ops = {  }; -static void snd_soc_instantiate_card(struct snd_soc_card *card) +static int soc_bind_dai_link(struct snd_soc_card *card, int num)  { -	struct platform_device *pdev = container_of(card->dev, -						    struct platform_device, -						    dev); -	struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; +	struct snd_soc_dai_link *dai_link = &card->dai_link[num]; +	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];  	struct snd_soc_codec *codec;  	struct snd_soc_platform *platform; -	struct snd_soc_dai *dai; -	int i, found, ret, ac97; +	struct snd_soc_dai *codec_dai, *cpu_dai; -	if (card->instantiated) -		return; +	if (rtd->complete) +		return 1; +	dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num); -	found = 0; -	list_for_each_entry(platform, &platform_list, list) -		if (card->platform == platform) { -			found = 1; -			break; +	/* do we already have the CPU DAI for this link ? */ +	if (rtd->cpu_dai) { +		goto find_codec; +	} +	/* no, then find CPU DAI from registered DAIs*/ +	list_for_each_entry(cpu_dai, &dai_list, list) { +		if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) { + +			if (!try_module_get(cpu_dai->dev->driver->owner)) +				return -ENODEV; + +			rtd->cpu_dai = cpu_dai; +			goto find_codec;  		} -	if (!found) { -		dev_dbg(card->dev, "Platform %s not registered\n", -			card->platform->name); -		return;  	} +	dev_dbg(card->dev, "CPU DAI %s not registered\n", +			dai_link->cpu_dai_name); -	ac97 = 0; -	for (i = 0; i < card->num_links; i++) { -		found = 0; -		list_for_each_entry(dai, &dai_list, list) -			if (card->dai_link[i].cpu_dai == dai) { -				found = 1; -				break; +find_codec: +	/* do we already have the CODEC for this link ? */ +	if (rtd->codec) { +		goto find_platform; +	} + +	/* no, then find CODEC from registered CODECs*/ +	list_for_each_entry(codec, &codec_list, list) { +		if (!strcmp(codec->name, dai_link->codec_name)) { +			rtd->codec = codec; + +			if (!try_module_get(codec->dev->driver->owner)) +				return -ENODEV; + +			/* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ +			list_for_each_entry(codec_dai, &dai_list, list) { +				if (codec->dev == codec_dai->dev && +						!strcmp(codec_dai->name, dai_link->codec_dai_name)) { +					rtd->codec_dai = codec_dai; +					goto find_platform; +				}  			} -		if (!found) { -			dev_dbg(card->dev, "DAI %s not registered\n", -				card->dai_link[i].cpu_dai->name); -			return; +			dev_dbg(card->dev, "CODEC DAI %s not registered\n", +					dai_link->codec_dai_name); + +			goto find_platform;  		} +	} +	dev_dbg(card->dev, "CODEC %s not registered\n", +			dai_link->codec_name); -		if (card->dai_link[i].cpu_dai->ac97_control) -			ac97 = 1; +find_platform: +	/* do we already have the CODEC DAI for this link ? */ +	if (rtd->platform) { +		goto out;  	} +	/* no, then find CPU DAI from registered DAIs*/ +	list_for_each_entry(platform, &platform_list, list) { +		if (!strcmp(platform->name, dai_link->platform_name)) { -	for (i = 0; i < card->num_links; i++) { -		if (!card->dai_link[i].codec_dai->ops) -			card->dai_link[i].codec_dai->ops = &null_dai_ops; +			if (!try_module_get(platform->dev->driver->owner)) +				return -ENODEV; + +			rtd->platform = platform; +			goto out; +		}  	} -	/* If we have AC97 in the system then don't wait for the -	 * codec.  This will need revisiting if we have to handle -	 * systems with mixed AC97 and non-AC97 parts.  Only check for -	 * DAIs currently; we can't do this per link since some AC97 -	 * codecs have non-AC97 DAIs. -	 */ -	if (!ac97) -		for (i = 0; i < card->num_links; i++) { -			found = 0; -			list_for_each_entry(dai, &dai_list, list) -				if (card->dai_link[i].codec_dai == dai) { -					found = 1; -					break; -				} -			if (!found) { -				dev_dbg(card->dev, "DAI %s not registered\n", -					card->dai_link[i].codec_dai->name); -				return; -			} +	dev_dbg(card->dev, "platform %s not registered\n", +			dai_link->platform_name); +	return 0; + +out: +	/* mark rtd as complete if we found all 4 of our client devices */ +	if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) { +		rtd->complete = 1; +		card->num_rtd++; +	} +	return 1; +} + +static void soc_remove_dai_link(struct snd_soc_card *card, int num) +{ +	struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; +	int err; + +	/* unregister the rtd device */ +	if (rtd->dev_registered) { +		device_remove_file(&rtd->dev, &dev_attr_pmdown_time); +		device_unregister(&rtd->dev); +		rtd->dev_registered = 0; +	} + +	/* remove the CODEC DAI */ +	if (codec_dai && codec_dai->probed) { +		if (codec_dai->driver->remove) { +			err = codec_dai->driver->remove(codec_dai); +			if (err < 0) +				printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);  		} +		codec_dai->probed = 0; +		list_del(&codec_dai->card_list); +	} -	/* Note that we do not current check for codec components */ +	/* remove the platform */ +	if (platform && platform->probed) { +		if (platform->driver->remove) { +			err = platform->driver->remove(platform); +			if (err < 0) +				printk(KERN_ERR "asoc: failed to remove %s\n", platform->name); +		} +		platform->probed = 0; +		list_del(&platform->card_list); +		module_put(platform->dev->driver->owner); +	} -	dev_dbg(card->dev, "All components present, instantiating\n"); +	/* remove the CODEC */ +	if (codec && codec->probed) { +		if (codec->driver->remove) { +			err = codec->driver->remove(codec); +			if (err < 0) +				printk(KERN_ERR "asoc: failed to remove %s\n", codec->name); +		} -	/* Found everything, bring it up */ -	card->pmdown_time = pmdown_time; +		/* Make sure all DAPM widgets are freed */ +		snd_soc_dapm_free(codec); -	if (card->probe) { -		ret = card->probe(pdev); -		if (ret < 0) -			return; +		soc_cleanup_codec_debugfs(codec); +		device_remove_file(&rtd->dev, &dev_attr_codec_reg); +		codec->probed = 0; +		list_del(&codec->card_list); +		module_put(codec->dev->driver->owner);  	} -	for (i = 0; i < card->num_links; i++) { -		struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; -		if (cpu_dai->probe) { -			ret = cpu_dai->probe(pdev, cpu_dai); -			if (ret < 0) -				goto cpu_dai_err; +	/* remove the cpu_dai */ +	if (cpu_dai && cpu_dai->probed) { +		if (cpu_dai->driver->remove) { +			err = cpu_dai->driver->remove(cpu_dai); +			if (err < 0) +				printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);  		} +		cpu_dai->probed = 0; +		list_del(&cpu_dai->card_list); +		module_put(cpu_dai->dev->driver->owner);  	} +} -	if (codec_dev->probe) { -		ret = codec_dev->probe(pdev); -		if (ret < 0) -			goto cpu_dai_err; +static void rtd_release(struct device *dev) {} + +static int soc_probe_dai_link(struct snd_soc_card *card, int num) +{ +	struct snd_soc_dai_link *dai_link = &card->dai_link[num]; +	struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; +	int ret; + +	dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); + +	/* config components */ +	codec_dai->codec = codec; +	codec->card = card; +	cpu_dai->platform = platform; +	rtd->card = card; +	rtd->dev.parent = card->dev; +	codec_dai->card = card; +	cpu_dai->card = card; + +	/* set default power off timeout */ +	rtd->pmdown_time = pmdown_time; + +	/* probe the cpu_dai */ +	if (!cpu_dai->probed) { +		if (cpu_dai->driver->probe) { +			ret = cpu_dai->driver->probe(cpu_dai); +			if (ret < 0) { +				printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n", +						cpu_dai->name); +				return ret; +			} +		} +		cpu_dai->probed = 1; +		/* mark cpu_dai as probed and add to card cpu_dai list */ +		list_add(&cpu_dai->card_list, &card->dai_dev_list);  	} -	codec = card->codec; -	if (platform->probe) { -		ret = platform->probe(pdev); -		if (ret < 0) -			goto platform_err; +	/* probe the CODEC */ +	if (!codec->probed) { +		if (codec->driver->probe) { +			ret = codec->driver->probe(codec); +			if (ret < 0) { +				printk(KERN_ERR "asoc: failed to probe CODEC %s\n", +						codec->name); +				return ret; +			} +		} +		/* mark codec as probed and add to card codec list */ +		codec->probed = 1; +		list_add(&codec->card_list, &card->codec_dev_list);  	} -	/* DAPM stream work */ -	INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); -#ifdef CONFIG_PM -	/* deferred resume work */ -	INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); -#endif +	/* probe the platform */ +	if (!platform->probed) { +		if (platform->driver->probe) { +			ret = platform->driver->probe(platform); +			if (ret < 0) { +				printk(KERN_ERR "asoc: failed to probe platform %s\n", +						platform->name); +				return ret; +			} +		} +		/* mark platform as probed and add to card platform list */ +		platform->probed = 1; +		list_add(&platform->card_list, &card->platform_dev_list); +	} -	for (i = 0; i < card->num_links; i++) { -		if (card->dai_link[i].init) { -			ret = card->dai_link[i].init(codec); +	/* probe the CODEC DAI */ +	if (!codec_dai->probed) { +		if (codec_dai->driver->probe) { +			ret = codec_dai->driver->probe(codec_dai);  			if (ret < 0) { -				printk(KERN_ERR "asoc: failed to init %s\n", -					card->dai_link[i].stream_name); -				continue; +				printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n", +						codec_dai->name); +				return ret;  			}  		} -		if (card->dai_link[i].codec_dai->ac97_control) -			ac97 = 1; + +		/* mark cpu_dai as probed and add to card cpu_dai list */ +		codec_dai->probed = 1; +		list_add(&codec_dai->card_list, &card->dai_dev_list);  	} -	snprintf(codec->card->shortname, sizeof(codec->card->shortname), -		 "%s",  card->name); -	snprintf(codec->card->longname, sizeof(codec->card->longname), -		 "%s (%s)", card->name, codec->name); +	/* DAPM dai link stream work */ +	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); + +	/* now that all clients have probed, initialise the DAI link */ +	if (dai_link->init) { +		ret = dai_link->init(rtd); +		if (ret < 0) { +			printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); +			return ret; +		} +	}  	/* Make sure all DAPM widgets are instantiated */  	snd_soc_dapm_new_widgets(codec); +	snd_soc_dapm_sync(codec); -	ret = snd_card_register(codec->card); +	/* register the rtd device */ +	rtd->dev.init_name = rtd->dai_link->stream_name; +	rtd->dev.release = rtd_release; +	rtd->dev.init_name = dai_link->name; +	ret = device_register(&rtd->dev);  	if (ret < 0) { -		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", -				codec->name); -		goto card_err; +		printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret); +		return ret;  	} -	mutex_lock(&codec->mutex); +	rtd->dev_registered = 1; +	ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); +	if (ret < 0) +		printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); + +	/* add DAPM sysfs entries for this codec */ +	ret = snd_soc_dapm_sys_add(&rtd->dev); +	if (ret < 0) +		printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n"); + +	/* add codec sysfs entries */ +	ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); +	if (ret < 0) +		printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); + +	soc_init_codec_debugfs(codec); + +	/* create the pcm */ +	ret = soc_new_pcm(rtd, num); +	if (ret < 0) { +		printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name); +		return ret; +	} + +	/* add platform data for AC97 devices */ +	if (rtd->codec_dai->driver->ac97_control) +		snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata); + +	return 0; +} +  #ifdef CONFIG_SND_SOC_AC97_BUS +static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) +{ +	int ret; +  	/* Only instantiate AC97 if not already done by the adaptor  	 * for the generic AC97 subsystem.  	 */ -	if (ac97 && strcmp(codec->name, "AC97") != 0) { -		ret = soc_ac97_dev_register(codec); +	if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) { + +		ret = soc_ac97_dev_register(rtd->codec);  		if (ret < 0) {  			printk(KERN_ERR "asoc: AC97 device register failed\n"); -			snd_card_free(codec->card); -			mutex_unlock(&codec->mutex); -			goto card_err; +			return ret;  		} + +		rtd->codec->ac97_registered = 1;  	} +	return 0; +} + +static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) +{ +	if (codec->ac97_registered) { +		soc_ac97_dev_unregister(codec); +		codec->ac97_registered = 0; +	} +}  #endif -	ret = snd_soc_dapm_sys_add(card->socdev->dev); -	if (ret < 0) -		printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); +static void snd_soc_instantiate_card(struct snd_soc_card *card) +{ +	struct platform_device *pdev = to_platform_device(card->dev); +	int ret, i; -	ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); -	if (ret < 0) -		printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); +	mutex_lock(&card->mutex); -	ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); -	if (ret < 0) -		printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); +	if (card->instantiated) { +		mutex_unlock(&card->mutex); +		return; +	} -	soc_init_codec_debugfs(codec); -	mutex_unlock(&codec->mutex); +	/* bind DAIs */ +	for (i = 0; i < card->num_links; i++) +		soc_bind_dai_link(card, i); -	card->instantiated = 1; +	/* bind completed ? */ +	if (card->num_rtd != card->num_links) { +		mutex_unlock(&card->mutex); +		return; +	} -	return; +	/* card bind complete so register a sound card */ +	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, +			card->owner, 0, &card->snd_card); +	if (ret < 0) { +		printk(KERN_ERR "asoc: can't create sound card for card %s\n", +			card->name); +		mutex_unlock(&card->mutex); +		return; +	} +	card->snd_card->dev = card->dev; + +#ifdef CONFIG_PM +	/* deferred resume work */ +	INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); +#endif -card_err: -	if (platform->remove) -		platform->remove(pdev); +	/* initialise the sound card only once */ +	if (card->probe) { +		ret = card->probe(pdev); +		if (ret < 0) +			goto card_probe_error; +	} -platform_err: -	if (codec_dev->remove) -		codec_dev->remove(pdev); +	for (i = 0; i < card->num_links; i++) { +		ret = soc_probe_dai_link(card, i); +		if (ret < 0) { +			printk(KERN_ERR "asoc: failed to instanciate card %s\n", card->name); +			goto probe_dai_err; +		} +	} -cpu_dai_err: -	for (i--; i >= 0; i--) { -		struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; -		if (cpu_dai->remove) -			cpu_dai->remove(pdev, cpu_dai); +	snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), +		 "%s",  card->name); +	snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), +		 "%s", card->name); + +	ret = snd_card_register(card->snd_card); +	if (ret < 0) { +		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); +		goto probe_dai_err;  	} +#ifdef CONFIG_SND_SOC_AC97_BUS +	/* register any AC97 codecs */ +	for (i = 0; i < card->num_rtd; i++) { +			ret = soc_register_ac97_dai_link(&card->rtd[i]); +			if (ret < 0) { +				printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); +				goto probe_dai_err; +			} +		} +#endif + +	card->instantiated = 1; +	mutex_unlock(&card->mutex); +	return; + +probe_dai_err: +	for (i = 0; i < card->num_links; i++) +		soc_remove_dai_link(card, i); + +card_probe_error:  	if (card->remove)  		card->remove(pdev); + +	snd_card_free(card->snd_card); + +	mutex_unlock(&card->mutex);  }  /* @@ -1332,15 +1552,15 @@ static void snd_soc_instantiate_cards(void)  /* probes a new socdev */  static int soc_probe(struct platform_device *pdev)  { +	struct snd_soc_card *card = platform_get_drvdata(pdev);  	int ret = 0; -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; - -	/* Bodge while we push things out of socdev */ -	card->socdev = socdev;  	/* Bodge while we unpick instantiation */  	card->dev = &pdev->dev; +	INIT_LIST_HEAD(&card->dai_dev_list); +	INIT_LIST_HEAD(&card->codec_dev_list); +	INIT_LIST_HEAD(&card->platform_dev_list); +  	ret = snd_soc_register_card(card);  	if (ret != 0) {  		dev_err(&pdev->dev, "Failed to register card\n"); @@ -1353,50 +1573,49 @@ static int soc_probe(struct platform_device *pdev)  /* removes a socdev */  static int soc_remove(struct platform_device *pdev)  { +	struct snd_soc_card *card = platform_get_drvdata(pdev);  	int i; -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_codec_device *codec_dev = socdev->codec_dev; -	if (card->instantiated) { -		run_delayed_work(&card->delayed_work); +		if (card->instantiated) { -		if (platform->remove) -			platform->remove(pdev); - -		if (codec_dev->remove) -			codec_dev->remove(pdev); - -		for (i = 0; i < card->num_links; i++) { -			struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; -			if (cpu_dai->remove) -				cpu_dai->remove(pdev, cpu_dai); +		/* make sure any delayed work runs */ +		for (i = 0; i < card->num_rtd; i++) { +			struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; +			run_delayed_work(&rtd->delayed_work);  		} +		/* remove and free each DAI */ +		for (i = 0; i < card->num_rtd; i++) +			soc_remove_dai_link(card, i); + +		/* remove the card */  		if (card->remove)  			card->remove(pdev); -	} +		kfree(card->rtd); +		snd_card_free(card->snd_card); +	}  	snd_soc_unregister_card(card); -  	return 0;  }  static int soc_poweroff(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct snd_soc_card *card = socdev->card; +	struct snd_soc_card *card = platform_get_drvdata(pdev); +	int i;  	if (!card->instantiated)  		return 0;  	/* Flush out pmdown_time work - we actually do want to run it  	 * now, we're shutting down so no imminent restart. */ -	run_delayed_work(&card->delayed_work); +	for (i = 0; i < card->num_rtd; i++) { +		struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; +		run_delayed_work(&rtd->delayed_work); +	} -	snd_soc_dapm_shutdown(socdev); +	snd_soc_dapm_shutdown(card);  	return 0;  } @@ -1419,53 +1638,42 @@ static struct platform_driver soc_driver = {  };  /* create a new pcm */ -static int soc_new_pcm(struct snd_soc_device *socdev, -	struct snd_soc_dai_link *dai_link, int num) -{ -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_codec *codec = card->codec; -	struct snd_soc_platform *platform = card->platform; -	struct snd_soc_dai *codec_dai = dai_link->codec_dai; -	struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; -	struct snd_soc_pcm_runtime *rtd; +static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +{ +	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_platform *platform = rtd->platform; +	struct snd_soc_dai *codec_dai = rtd->codec_dai; +	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;  	struct snd_pcm *pcm;  	char new_name[64];  	int ret = 0, playback = 0, capture = 0; -	rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL); -	if (rtd == NULL) -		return -ENOMEM; - -	rtd->dai = dai_link; -	rtd->socdev = socdev; -	codec_dai->codec = card->codec; -  	/* check client and interface hw capabilities */  	snprintf(new_name, sizeof(new_name), "%s %s-%d", -		 dai_link->stream_name, codec_dai->name, num); +			rtd->dai_link->stream_name, codec_dai->name, num); -	if (codec_dai->playback.channels_min) +	if (codec_dai->driver->playback.channels_min)  		playback = 1; -	if (codec_dai->capture.channels_min) +	if (codec_dai->driver->capture.channels_min)  		capture = 1; -	ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, -		capture, &pcm); +	dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); +	ret = snd_pcm_new(rtd->card->snd_card, new_name, +			num, playback, capture, &pcm);  	if (ret < 0) { -		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", -			codec->name); -		kfree(rtd); +		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);  		return ret;  	} -	dai_link->pcm = pcm; +	rtd->pcm = pcm;  	pcm->private_data = rtd; -	soc_pcm_ops.mmap = platform->pcm_ops->mmap; -	soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; -	soc_pcm_ops.copy = platform->pcm_ops->copy; -	soc_pcm_ops.silence = platform->pcm_ops->silence; -	soc_pcm_ops.ack = platform->pcm_ops->ack; -	soc_pcm_ops.page = platform->pcm_ops->page; +	soc_pcm_ops.mmap = platform->driver->ops->mmap; +	soc_pcm_ops.pointer = platform->driver->ops->pointer; +	soc_pcm_ops.ioctl = platform->driver->ops->ioctl; +	soc_pcm_ops.copy = platform->driver->ops->copy; +	soc_pcm_ops.silence = platform->driver->ops->silence; +	soc_pcm_ops.ack = platform->driver->ops->ack; +	soc_pcm_ops.page = platform->driver->ops->page;  	if (playback)  		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); @@ -1473,14 +1681,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,  	if (capture)  		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); -	ret = platform->pcm_new(codec->card, codec_dai, pcm); +	ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm);  	if (ret < 0) {  		printk(KERN_ERR "asoc: platform pcm constructor failed\n"); -		kfree(rtd);  		return ret;  	} -	pcm->private_free = platform->pcm_free; +	pcm->private_free = platform->driver->pcm_free;  	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,  		cpu_dai->name);  	return ret; @@ -1496,8 +1703,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,   */  int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)  { -	if (codec->volatile_register) -		return codec->volatile_register(reg); +	if (codec->driver->volatile_register) +		return codec->driver->volatile_register(reg);  	else  		return 0;  } @@ -1532,7 +1739,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,  	codec->ac97->bus->ops = ops;  	codec->ac97->num = num; -	codec->dev = &codec->ac97->dev;  	mutex_unlock(&codec->mutex);  	return 0;  } @@ -1547,6 +1753,9 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);  void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)  {  	mutex_lock(&codec->mutex); +#ifdef CONFIG_SND_SOC_AC97_BUS +	soc_unregister_ac97_dai_link(codec); +#endif  	kfree(codec->ac97->bus);  	kfree(codec->ac97);  	codec->ac97 = NULL; @@ -1633,95 +1842,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,  EXPORT_SYMBOL_GPL(snd_soc_test_bits);  /** - * snd_soc_new_pcms - create new sound card and pcms - * @socdev: the SoC audio device - * @idx: ALSA card index - * @xid: card identification - * - * Create a new sound card based upon the codec and interface pcms. - * - * Returns 0 for success, else error. - */ -int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) -{ -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_codec *codec = card->codec; -	int ret, i; - -	mutex_lock(&codec->mutex); - -	/* register a sound card */ -	ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); -	if (ret < 0) { -		printk(KERN_ERR "asoc: can't create sound card for codec %s\n", -			codec->name); -		mutex_unlock(&codec->mutex); -		return ret; -	} - -	codec->socdev = socdev; -	codec->card->dev = socdev->dev; -	codec->card->private_data = codec; -	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); - -	/* create the pcms */ -	for (i = 0; i < card->num_links; i++) { -		ret = soc_new_pcm(socdev, &card->dai_link[i], i); -		if (ret < 0) { -			printk(KERN_ERR "asoc: can't create pcm %s\n", -				card->dai_link[i].stream_name); -			mutex_unlock(&codec->mutex); -			return ret; -		} -		/* Check for codec->ac97 to handle the ac97.c fun */ -		if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) { -			snd_ac97_dev_add_pdata(codec->ac97, -				card->dai_link[i].cpu_dai->ac97_pdata); -		} -	} - -	mutex_unlock(&codec->mutex); -	return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_new_pcms); - -/** - * snd_soc_free_pcms - free sound card and pcms - * @socdev: the SoC audio device - * - * Frees sound card and pcms associated with the socdev. - * Also unregister the codec if it is an AC97 device. - */ -void snd_soc_free_pcms(struct snd_soc_device *socdev) -{ -	struct snd_soc_codec *codec = socdev->card->codec; -#ifdef CONFIG_SND_SOC_AC97_BUS -	struct snd_soc_dai *codec_dai; -	int i; -#endif - -	mutex_lock(&codec->mutex); -	soc_cleanup_codec_debugfs(codec); -#ifdef CONFIG_SND_SOC_AC97_BUS -	for (i = 0; i < codec->num_dai; i++) { -		codec_dai = &codec->dai[i]; -		if (codec_dai->ac97_control && codec->ac97 && -		    strcmp(codec->name, "AC97") != 0) { -			soc_ac97_dev_unregister(codec); -			goto free_card; -		} -	} -free_card: -#endif - -	if (codec->card) -		snd_card_free(codec->card); -	device_remove_file(socdev->dev, &dev_attr_codec_reg); -	mutex_unlock(&codec->mutex); -} -EXPORT_SYMBOL_GPL(snd_soc_free_pcms); - -/**   * snd_soc_set_runtime_hwparams - set the runtime hardware parameters   * @substream: the pcm substream   * @hw: the hardware parameters @@ -1782,7 +1902,7 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);  int snd_soc_add_controls(struct snd_soc_codec *codec,  	const struct snd_kcontrol_new *controls, int num_controls)  { -	struct snd_card *card = codec->card; +	struct snd_card *card = codec->card->snd_card;  	int err, i;  	for (i = 0; i < num_controls; i++) { @@ -2337,7 +2457,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);  int snd_soc_limit_volume(struct snd_soc_codec *codec,  	const char *name, int max)  { -	struct snd_card *card = codec->card; +	struct snd_card *card = codec->card->snd_card;  	struct snd_kcontrol *kctl;  	struct soc_mixer_control *mc;  	int found = 0; @@ -2469,8 +2589,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);  int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,  	unsigned int freq, int dir)  { -	if (dai->ops && dai->ops->set_sysclk) -		return dai->ops->set_sysclk(dai, clk_id, freq, dir); +	if (dai->driver && dai->driver->ops->set_sysclk) +		return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);  	else  		return -EINVAL;  } @@ -2489,8 +2609,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 && dai->ops->set_clkdiv) -		return dai->ops->set_clkdiv(dai, div_id, div); +	if (dai->driver && dai->driver->ops->set_clkdiv) +		return dai->driver->ops->set_clkdiv(dai, div_id, div);  	else  		return -EINVAL;  } @@ -2509,8 +2629,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);  int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,  	unsigned int freq_in, unsigned int freq_out)  { -	if (dai->ops && dai->ops->set_pll) -		return dai->ops->set_pll(dai, pll_id, source, +	if (dai->driver && dai->driver->ops->set_pll) +		return dai->driver->ops->set_pll(dai, pll_id, source,  					 freq_in, freq_out);  	else  		return -EINVAL; @@ -2526,8 +2646,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 && dai->ops->set_fmt) -		return dai->ops->set_fmt(dai, fmt); +	if (dai->driver && dai->driver->ops->set_fmt) +		return dai->driver->ops->set_fmt(dai, fmt);  	else  		return -EINVAL;  } @@ -2547,8 +2667,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);  int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,  	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)  { -	if (dai->ops && dai->ops->set_tdm_slot) -		return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, +	if (dai->driver && dai->driver->ops->set_tdm_slot) +		return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,  				slots, slot_width);  	else  		return -EINVAL; @@ -2571,8 +2691,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,  	unsigned int tx_num, unsigned int *tx_slot,  	unsigned int rx_num, unsigned int *rx_slot)  { -	if (dai->ops && dai->ops->set_channel_map) -		return dai->ops->set_channel_map(dai, tx_num, tx_slot, +	if (dai->driver && dai->driver->ops->set_channel_map) +		return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,  			rx_num, rx_slot);  	else  		return -EINVAL; @@ -2588,8 +2708,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);   */  int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)  { -	if (dai->ops && dai->ops->set_tristate) -		return dai->ops->set_tristate(dai, tristate); +	if (dai->driver && dai->driver->ops->set_tristate) +		return dai->driver->ops->set_tristate(dai, tristate);  	else  		return -EINVAL;  } @@ -2604,8 +2724,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 && dai->ops->digital_mute) -		return dai->ops->digital_mute(dai, mute); +	if (dai->driver && dai->driver->ops->digital_mute) +		return dai->driver->ops->digital_mute(dai, mute);  	else  		return -EINVAL;  } @@ -2622,11 +2742,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);   */  static int snd_soc_register_card(struct snd_soc_card *card)  { +	int i; +  	if (!card->name || !card->dev)  		return -EINVAL; +	card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links, +			GFP_KERNEL); +	if (card->rtd == NULL) +		return -ENOMEM; + +	for (i = 0; i < card->num_links; i++) +		card->rtd[i].dai_link = &card->dai_link[i]; +  	INIT_LIST_HEAD(&card->list);  	card->instantiated = 0; +	mutex_init(&card->mutex);  	mutex_lock(&client_mutex);  	list_add(&card->list, &card_list); @@ -2652,30 +2783,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)  	mutex_lock(&client_mutex);  	list_del(&card->list);  	mutex_unlock(&client_mutex); -  	dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);  	return 0;  } +/* + * Simplify DAI link configuration by removing ".-1" from device names + * and sanitizing names. + */ +static inline char *fmt_single_name(struct device *dev, int *id) +{ +	char *found, name[NAME_SIZE]; +	int id1, id2; + +	if (dev_name(dev) == NULL) +		return NULL; + +	strncpy(name, dev_name(dev), NAME_SIZE); + +	/* are we a "%s.%d" name (platform and SPI components) */ +	found = strstr(name, dev->driver->name); +	if (found) { +		/* get ID */ +		if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) { + +			/* discard ID from name if ID == -1 */ +			if (*id == -1) +				found[strlen(dev->driver->name)] = '\0'; +		} + +	} else { +		/* I2C component devices are named "bus-addr"  */ +		if (sscanf(name, "%x-%x", &id1, &id2) == 2) { +			char tmp[NAME_SIZE]; + +			/* create unique ID number from I2C addr and bus */ +			*id = ((id1 && 0xffff) << 16) + id2; + +			/* sanitize component name for DAI link creation */ +			snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); +			strncpy(name, tmp, NAME_SIZE); +		} else +			*id = 0; +	} + +	return kstrdup(name, GFP_KERNEL); +} + +/* + * Simplify DAI link naming for single devices with multiple DAIs by removing + * any ".-1" and using the DAI name (instead of device name). + */ +static inline char *fmt_multiple_name(struct device *dev, +		struct snd_soc_dai_driver *dai_drv) +{ +	if (dai_drv->name == NULL) { +		printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n", +				dev_name(dev)); +		return NULL; +	} + +	return kstrdup(dai_drv->name, GFP_KERNEL); +} +  /**   * snd_soc_register_dai - Register a DAI with the ASoC core   *   * @dai: DAI to register   */ -int snd_soc_register_dai(struct snd_soc_dai *dai) +int snd_soc_register_dai(struct device *dev, +		struct snd_soc_dai_driver *dai_drv)  { -	if (!dai->name) -		return -EINVAL; +	struct snd_soc_dai *dai; + +	dev_dbg(dev, "dai register %s\n", dev_name(dev)); -	/* The device should become mandatory over time */ -	if (!dai->dev) -		printk(KERN_WARNING "No device for DAI %s\n", dai->name); +	dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); +	if (dai == NULL) +			return -ENOMEM; -	if (!dai->ops) -		dai->ops = &null_dai_ops; +	/* create DAI component name */ +	dai->name = fmt_single_name(dev, &dai->id); +	if (dai->name == NULL) { +		kfree(dai); +		return -ENOMEM; +	} -	INIT_LIST_HEAD(&dai->list); +	dai->dev = dev; +	dai->driver = dai_drv; +	if (!dai->driver->ops) +		dai->driver->ops = &null_dai_ops;  	mutex_lock(&client_mutex);  	list_add(&dai->list, &dai_list); @@ -2693,13 +2891,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai);   *   * @dai: DAI to unregister   */ -void snd_soc_unregister_dai(struct snd_soc_dai *dai) +void snd_soc_unregister_dai(struct device *dev)  { +	struct snd_soc_dai *dai; + +	list_for_each_entry(dai, &dai_list, list) { +		if (dev == dai->dev) +			goto found; +	} +	return; + +found:  	mutex_lock(&client_mutex);  	list_del(&dai->list);  	mutex_unlock(&client_mutex);  	pr_debug("Unregistered DAI '%s'\n", dai->name); +	kfree(dai->name); +	kfree(dai);  }  EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); @@ -2709,21 +2918,47 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);   * @dai: Array of DAIs to register   * @count: Number of DAIs   */ -int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) +int snd_soc_register_dais(struct device *dev, +		struct snd_soc_dai_driver *dai_drv, size_t count)  { -	int i, ret; +	struct snd_soc_dai *dai; +	int i, ret = 0; + +	dev_dbg(dev, "dai register %s #%d\n", dev_name(dev), count);  	for (i = 0; i < count; i++) { -		ret = snd_soc_register_dai(&dai[i]); -		if (ret != 0) + +		dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); +		if (dai == NULL) +			return -ENOMEM; + +		/* create DAI component name */ +		dai->name = fmt_multiple_name(dev, &dai_drv[i]); +		if (dai->name == NULL) { +			kfree(dai); +			ret = -EINVAL;  			goto err; +		} + +		dai->dev = dev; +		dai->id = i; +		dai->driver = &dai_drv[i]; +		if (!dai->driver->ops) +			dai->driver->ops = &null_dai_ops; + +		mutex_lock(&client_mutex); +		list_add(&dai->list, &dai_list); +		mutex_unlock(&client_mutex); + +		pr_debug("Registered DAI '%s'\n", dai->name);  	} +	snd_soc_instantiate_cards();  	return 0;  err:  	for (i--; i >= 0; i--) -		snd_soc_unregister_dai(&dai[i]); +		snd_soc_unregister_dai(dev);  	return ret;  } @@ -2735,12 +2970,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);   * @dai: Array of DAIs to unregister   * @count: Number of DAIs   */ -void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) +void snd_soc_unregister_dais(struct device *dev, size_t count)  {  	int i;  	for (i = 0; i < count; i++) -		snd_soc_unregister_dai(&dai[i]); +		snd_soc_unregister_dai(dev);  }  EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); @@ -2749,12 +2984,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);   *   * @platform: platform to register   */ -int snd_soc_register_platform(struct snd_soc_platform *platform) +int snd_soc_register_platform(struct device *dev, +		struct snd_soc_platform_driver *platform_drv)  { -	if (!platform->name) -		return -EINVAL; +	struct snd_soc_platform *platform; + +	dev_dbg(dev, "platform register %s\n", dev_name(dev)); + +	platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL); +	if (platform == NULL) +			return -ENOMEM; + +	/* create platform component name */ +	platform->name = fmt_single_name(dev, &platform->id); +	if (platform->name == NULL) { +		kfree(platform); +		return -ENOMEM; +	} -	INIT_LIST_HEAD(&platform->list); +	platform->dev = dev; +	platform->driver = platform_drv;  	mutex_lock(&client_mutex);  	list_add(&platform->list, &platform_list); @@ -2772,13 +3021,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);   *   * @platform: platform to unregister   */ -void snd_soc_unregister_platform(struct snd_soc_platform *platform) +void snd_soc_unregister_platform(struct device *dev)  { +	struct snd_soc_platform *platform; + +	list_for_each_entry(platform, &platform_list, list) { +		if (dev == platform->dev) +			goto found; +	} +	return; + +found:  	mutex_lock(&client_mutex);  	list_del(&platform->list);  	mutex_unlock(&client_mutex);  	pr_debug("Unregistered platform '%s'\n", platform->name); +	kfree(platform->name); +	kfree(platform);  }  EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); @@ -2820,32 +3080,78 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)   *   * @codec: codec to register   */ -int snd_soc_register_codec(struct snd_soc_codec *codec) +int snd_soc_register_codec(struct device *dev, +		struct snd_soc_codec_driver *codec_drv, +		struct snd_soc_dai_driver *dai_drv, int num_dai)  { -	int i; +	struct snd_soc_codec *codec; +	int ret, i; -	if (!codec->name) -		return -EINVAL; +	dev_dbg(dev, "codec register %s\n", dev_name(dev)); + +	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); +	if (codec == NULL) +		return -ENOMEM; -	/* The device should become mandatory over time */ -	if (!codec->dev) -		printk(KERN_WARNING "No device for codec %s\n", codec->name); +	/* create CODEC component name */ +	codec->name = fmt_single_name(dev, &codec->id); +	if (codec->name == NULL) { +		kfree(codec); +		return -ENOMEM; +	} + +	/* allocate CODEC register cache */ +	if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { -	INIT_LIST_HEAD(&codec->list); +		if (codec_drv->reg_cache_default) +			codec->reg_cache = kmemdup(codec_drv->reg_cache_default, +				codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); +		else +			codec->reg_cache = kzalloc(codec_drv->reg_cache_size * +				codec_drv->reg_word_size, GFP_KERNEL); -	for (i = 0; i < codec->num_dai; i++) { -		fixup_codec_formats(&codec->dai[i].playback); -		fixup_codec_formats(&codec->dai[i].capture); +		if (codec->reg_cache == NULL) { +			kfree(codec->name); +			kfree(codec); +			return -ENOMEM; +		}  	} +	codec->dev = dev; +	codec->driver = codec_drv; +	codec->bias_level = SND_SOC_BIAS_OFF; +	codec->num_dai = num_dai; +	mutex_init(&codec->mutex); +	INIT_LIST_HEAD(&codec->dapm_widgets); +	INIT_LIST_HEAD(&codec->dapm_paths); + +	for (i = 0; i < num_dai; i++) { +		fixup_codec_formats(&dai_drv[i].playback); +		fixup_codec_formats(&dai_drv[i].capture); +	} + +	/* register DAIs */ +	ret = snd_soc_register_dais(dev, dai_drv, num_dai); +	if (ret < 0) +			goto error; +  	mutex_lock(&client_mutex);  	list_add(&codec->list, &codec_list);  	snd_soc_instantiate_cards();  	mutex_unlock(&client_mutex);  	pr_debug("Registered codec '%s'\n", codec->name); -  	return 0; + +error: +	for (i--; i >= 0; i--) +		snd_soc_unregister_dai(dev); + +	if (codec->reg_cache) +		kfree(codec->reg_cache); +	kfree(codec->name); +	kfree(codec); +	return ret;  }  EXPORT_SYMBOL_GPL(snd_soc_register_codec); @@ -2854,13 +3160,30 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);   *   * @codec: codec to unregister   */ -void snd_soc_unregister_codec(struct snd_soc_codec *codec) +void snd_soc_unregister_codec(struct device *dev)  { +	struct snd_soc_codec *codec; +	int i; + +	list_for_each_entry(codec, &codec_list, list) { +		if (dev == codec->dev) +			goto found; +	} +	return; + +found: +	for (i = 0; i < codec->num_dai; i++) +		snd_soc_unregister_dai(dev); +  	mutex_lock(&client_mutex);  	list_del(&codec->list);  	mutex_unlock(&client_mutex);  	pr_debug("Unregistered codec '%s'\n", codec->name); + +	if (codec->reg_cache) +		kfree(codec->reg_cache); +	kfree(codec);  }  EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 03cb7c05ebec..035cab85cb66 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -112,43 +112,41 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(  /**   * snd_soc_dapm_set_bias_level - set the bias level for the system - * @socdev: audio device + * @card: audio device   * @level: level to configure   *   * Configure the bias (power) levels for the SoC audio device.   *   * Returns 0 for success else error.   */ -static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, -				       enum snd_soc_bias_level level) +static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, +		struct snd_soc_codec *codec, enum snd_soc_bias_level level)  { -	struct snd_soc_card *card = socdev->card; -	struct snd_soc_codec *codec = socdev->card->codec;  	int ret = 0;  	switch (level) {  	case SND_SOC_BIAS_ON: -		dev_dbg(socdev->dev, "Setting full bias\n"); +		dev_dbg(codec->dev, "Setting full bias\n");  		break;  	case SND_SOC_BIAS_PREPARE: -		dev_dbg(socdev->dev, "Setting bias prepare\n"); +		dev_dbg(codec->dev, "Setting bias prepare\n");  		break;  	case SND_SOC_BIAS_STANDBY: -		dev_dbg(socdev->dev, "Setting standby bias\n"); +		dev_dbg(codec->dev, "Setting standby bias\n");  		break;  	case SND_SOC_BIAS_OFF: -		dev_dbg(socdev->dev, "Setting bias off\n"); +		dev_dbg(codec->dev, "Setting bias off\n");  		break;  	default: -		dev_err(socdev->dev, "Setting invalid bias %d\n", level); +		dev_err(codec->dev, "Setting invalid bias %d\n", level);  		return -EINVAL;  	} -	if (card->set_bias_level) +	if (card && card->set_bias_level)  		ret = card->set_bias_level(card, level);  	if (ret == 0) { -		if (codec->set_bias_level) -			ret = codec->set_bias_level(codec, level); +		if (codec->driver->set_bias_level) +			ret = codec->driver->set_bias_level(codec, level);  		else  			codec->bias_level = level;  	} @@ -370,7 +368,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,  			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,  				path->long_name); -			ret = snd_ctl_add(codec->card, path->kcontrol); +			ret = snd_ctl_add(codec->card->snd_card, path->kcontrol);  			if (ret < 0) {  				printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",  				       path->long_name, @@ -398,7 +396,7 @@ static int dapm_new_mux(struct snd_soc_codec *codec,  	}  	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); -	ret = snd_ctl_add(codec->card, kcontrol); +	ret = snd_ctl_add(codec->card->snd_card, kcontrol);  	if (ret < 0)  		goto err; @@ -437,9 +435,9 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec)   */  static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)  { -	struct snd_soc_codec *codec = widget->codec; +	int level = snd_power_get_state(widget->codec->card->snd_card); -	switch (snd_power_get_state(codec->card)) { +	switch (level) {  	case SNDRV_CTL_POWER_D3hot:  	case SNDRV_CTL_POWER_D3cold:  		if (widget->ignore_suspend) @@ -893,7 +891,7 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,   */  static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  { -	struct snd_soc_device *socdev = codec->socdev; +	struct snd_soc_card *card = codec->card;  	struct snd_soc_dapm_widget *w;  	LIST_HEAD(up_list);  	LIST_HEAD(down_list); @@ -966,7 +964,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  	}  	if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { -		ret = snd_soc_dapm_set_bias_level(socdev, +		ret = snd_soc_dapm_set_bias_level(card, codec,  						  SND_SOC_BIAS_STANDBY);  		if (ret != 0)  			pr_err("Failed to turn on bias: %d\n", ret); @@ -975,8 +973,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  	/* If we're changing to all on or all off then prepare */  	if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||  	    (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { -		ret = snd_soc_dapm_set_bias_level(socdev, -						  SND_SOC_BIAS_PREPARE); +		ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE);  		if (ret != 0)  			pr_err("Failed to prepare bias: %d\n", ret);  	} @@ -989,8 +986,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  	/* If we just powered the last thing off drop to standby bias */  	if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { -		ret = snd_soc_dapm_set_bias_level(socdev, -						  SND_SOC_BIAS_STANDBY); +		ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY);  		if (ret != 0)  			pr_err("Failed to apply standby bias: %d\n", ret);  	} @@ -998,15 +994,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  	/* If we're in standby and can support bias off then do that */  	if (codec->bias_level == SND_SOC_BIAS_STANDBY &&  	    codec->idle_bias_off) { -		ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); +		ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);  		if (ret != 0)  			pr_err("Failed to turn off bias: %d\n", ret);  	}  	/* If we just powered up then move to active bias */  	if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { -		ret = snd_soc_dapm_set_bias_level(socdev, -						  SND_SOC_BIAS_ON); +		ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON);  		if (ret != 0)  			pr_err("Failed to apply active bias: %d\n", ret);  	} @@ -1188,8 +1183,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,  static ssize_t dapm_widget_show(struct device *dev,  	struct device_attribute *attr, char *buf)  { -	struct snd_soc_device *devdata = dev_get_drvdata(dev); -	struct snd_soc_codec *codec = devdata->card->codec; +	struct snd_soc_pcm_runtime *rtd = +			container_of(dev, struct snd_soc_pcm_runtime, dev); +	struct snd_soc_codec *codec =rtd->codec;  	struct snd_soc_dapm_widget *w;  	int count = 0;  	char *state = "not set"; @@ -1998,9 +1994,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);   *   * Returns 0 for success else error.   */ -int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, -	char *stream, int event) +int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, +	const char *stream, int event)  { +	struct snd_soc_codec *codec = rtd->codec;  	struct snd_soc_dapm_widget *w;  	if (stream == NULL) @@ -2168,25 +2165,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);  /**   * snd_soc_dapm_free - free dapm resources - * @socdev: SoC device + * @card: SoC device   *   * Free all dapm widgets and resources.   */ -void snd_soc_dapm_free(struct snd_soc_device *socdev) +void snd_soc_dapm_free(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec; - -	snd_soc_dapm_sys_remove(socdev->dev); +	snd_soc_dapm_sys_remove(codec->dev);  	dapm_free_widgets(codec);  }  EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -/* - * snd_soc_dapm_shutdown - callback for system shutdown - */ -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) +static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec)  { -	struct snd_soc_codec *codec = socdev->card->codec;  	struct snd_soc_dapm_widget *w;  	LIST_HEAD(down_list);  	int powerdown = 0; @@ -2203,12 +2194,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)  	 * standby.  	 */  	if (powerdown) { -		snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); +		snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE);  		dapm_seq_run(codec, &down_list, 0, dapm_down_seq); -		snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); +		snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY);  	} +} + +/* + * snd_soc_dapm_shutdown - callback for system shutdown + */ +void snd_soc_dapm_shutdown(struct snd_soc_card *card) +{ +	struct snd_soc_codec *codec; + +	list_for_each_entry(codec, &card->codec_dev_list, list) +		soc_dapm_shutdown_codec(codec); -	snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); +	snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);  }  /* Module information */ diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 29159e1781d0..8862770aa221 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -32,14 +32,14 @@   * Returns zero if successful, or a negative error code on failure.   * On success jack will be initialised.   */ -int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, +int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,  		     struct snd_soc_jack *jack)  { -	jack->card = card; +	jack->codec = codec;  	INIT_LIST_HEAD(&jack->pins);  	BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); -	return snd_jack_new(card->codec->card, id, type, &jack->jack); +	return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);  }  EXPORT_SYMBOL_GPL(snd_soc_jack_new); @@ -67,7 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)  	if (!jack)  		return; -	codec = jack->card->codec; +	codec = jack->codec;  	mutex_lock(&codec->mutex); @@ -268,7 +268,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,  		ret = request_irq(gpio_to_irq(gpios[i].gpio),  				gpio_handler,  				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, -				jack->card->dev->driver->name, +				jack->codec->dev->driver->name,  				&gpios[i]);  		if (ret)  			goto err; diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 0ec20b68e8cb..743d07b82c06 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c @@ -36,13 +36,11 @@  static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); -/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */ -static struct txx9aclc_soc_device *txx9aclc_soc_dev; +/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ +static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; -static int txx9aclc_regready(struct txx9aclc_soc_device *dev) +static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)  { -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); -  	return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;  } @@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev)  static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,  					 unsigned short reg)  { -	struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;  	void __iomem *base = drvdata->base;  	u32 dat; @@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,  	dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;  	__raw_writel(dat, base + ACREGACC);  	__raw_writel(ACINT_REGACCRDY, base + ACINTEN); -	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { +	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {  		__raw_writel(ACINT_REGACCRDY, base + ACINTDIS); -		dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg); +		printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);  		dat = 0xffff;  		goto done;  	}  	dat = __raw_readl(base + ACREGACC);  	if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { -		dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n", +		printk(KERN_ERR "reg mismatch %x with %x\n",  			dat, reg);  		dat = 0xffff;  		goto done; @@ -84,16 +81,15 @@ done:  static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,  				unsigned short val)  { -	struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;  	void __iomem *base = drvdata->base;  	__raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |  		     (val << ACREGACC_DAT_SHIFT),  		     base + ACREGACC);  	__raw_writel(ACINT_REGACCRDY, base + ACINTEN); -	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { -		dev_err(dev->soc_dev.dev, +	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { +		printk(KERN_ERR  			"ac97 write timeout (reg %#x)\n", reg);  	}  	__raw_writel(ACINT_REGACCRDY, base + ACINTDIS); @@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,  static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)  { -	struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;  	void __iomem *base = drvdata->base;  	u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; @@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static int txx9aclc_ac97_probe(struct platform_device *pdev, -			       struct snd_soc_dai *dai) +static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct txx9aclc_soc_device *dev = -		container_of(socdev, struct txx9aclc_soc_device, soc_dev); - -	dev->aclc_pdev = to_platform_device(dai->dev); -	txx9aclc_soc_dev = dev; +	txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);  	return 0;  } -static void txx9aclc_ac97_remove(struct platform_device *pdev, -				 struct snd_soc_dai *dai) +static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)  { -	struct platform_device *aclc_pdev = to_platform_device(dai->dev); -	struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev); +	struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);  	/* disable AC-link */  	__raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); -	txx9aclc_soc_dev = NULL; +	txx9aclc_drvdata = NULL; +	return 0;  } -struct snd_soc_dai txx9aclc_ac97_dai = { -	.name			= "txx9aclc_ac97", +static struct snd_soc_dai_driver txx9aclc_ac97_dai = {  	.ac97_control		= 1,  	.probe			= txx9aclc_ac97_probe,  	.remove			= txx9aclc_ac97_remove, @@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = {  		.channels_max	= 2,  	},  }; -EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);  static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)  { @@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)  	if (err < 0)  		return err; -	txx9aclc_ac97_dai.dev = &pdev->dev; -	return snd_soc_register_dai(&txx9aclc_ac97_dai); +	return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);  }  static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)  { -	snd_soc_unregister_dai(&txx9aclc_ac97_dai); +	snd_soc_unregister_dai(&pdev->dev);  	return 0;  } diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c index 95b17f731aec..6770e7166be4 100644 --- a/sound/soc/txx9/txx9aclc-generic.c +++ b/sound/soc/txx9/txx9aclc-generic.c @@ -19,54 +19,44 @@  #include <sound/core.h>  #include <sound/pcm.h>  #include <sound/soc.h> -#include "../codecs/ac97.h"  #include "txx9aclc.h"  static struct snd_soc_dai_link txx9aclc_generic_dai = {  	.name = "AC97",  	.stream_name = "AC97 HiFi", -	.cpu_dai = &txx9aclc_ac97_dai, -	.codec_dai = &ac97_dai, +	.cpu_dai_name = "txx9aclc-ac97", +	.codec_dai_name = "ac97-hifi", +	.platform_name	= "txx9aclc-pcm-audio", +	.codec_name	= "ac97-codec",  };  static struct snd_soc_card txx9aclc_generic_card = {  	.name		= "Generic TXx9 ACLC Audio", -	.platform	= &txx9aclc_soc_platform,  	.dai_link	= &txx9aclc_generic_dai,  	.num_links	= 1,  }; -static struct txx9aclc_soc_device txx9aclc_generic_soc_device = { -	.soc_dev = { -		.card		= &txx9aclc_generic_card, -		.codec_dev	= &soc_codec_dev_ac97, -	}, -}; +static struct platform_device *soc_pdev;  static int __init txx9aclc_generic_probe(struct platform_device *pdev)  { -	struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device; -	struct platform_device *soc_pdev;  	int ret;  	soc_pdev = platform_device_alloc("soc-audio", -1);  	if (!soc_pdev)  		return -ENOMEM; -	platform_set_drvdata(soc_pdev, &dev->soc_dev); -	dev->soc_dev.dev = &soc_pdev->dev; +	platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);  	ret = platform_device_add(soc_pdev);  	if (ret) {  		platform_device_put(soc_pdev);  		return ret;  	} -	platform_set_drvdata(pdev, soc_pdev); +  	return 0;  }  static int __exit txx9aclc_generic_remove(struct platform_device *pdev)  { -	struct platform_device *soc_pdev = platform_get_drvdata(pdev); -  	platform_device_unregister(soc_pdev);  	return 0;  } diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 0e3452303ea6..f4aa4e03c888 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -22,6 +22,16 @@  #include <sound/soc.h>  #include "txx9aclc.h" +static struct txx9aclc_soc_device { +	struct txx9aclc_dmadata dmadata[2]; +} txx9aclc_soc_device; + +/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ +static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; + +static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, +			     struct txx9aclc_dmadata *dmadata); +  static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {  	/*  	 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID @@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,  				  struct snd_pcm_hw_params *params)  {  	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); -	struct snd_soc_device *socdev = rtd->socdev;  	struct snd_pcm_runtime *runtime = substream->runtime;  	struct txx9aclc_dmadata *dmadata = runtime->private_data;  	int ret; @@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,  	if (ret < 0)  		return ret; -	dev_dbg(socdev->dev, +	dev_dbg(rtd->platform->dev,  		"runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "  		"runtime->min_align %ld\n",  		(unsigned long)runtime->dma_area,  		(unsigned long)runtime->dma_addr, runtime->dma_bytes,  		runtime->min_align); -	dev_dbg(socdev->dev, +	dev_dbg(rtd->platform->dev,  		"periods %d period_bytes %d stream %d\n",  		params_periods(params), params_period_bytes(params),  		substream->stream); @@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)  	spin_lock_irqsave(&dmadata->dma_lock, flags);  	if (dmadata->frag_count < 0) { -		struct txx9aclc_soc_device *dev = -			container_of(dmadata, struct txx9aclc_soc_device, -				     dmadata[substream->stream]); -		struct txx9aclc_plat_drvdata *drvdata = -			txx9aclc_get_plat_drvdata(dev); +		struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;  		void __iomem *base = drvdata->base;  		spin_unlock_irqrestore(&dmadata->dma_lock, flags); @@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)  static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)  {  	struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct txx9aclc_soc_device *dev = -		container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;  	void __iomem *base = drvdata->base;  	unsigned long flags;  	int ret = 0; @@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream)  static int txx9aclc_pcm_open(struct snd_pcm_substream *substream)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct txx9aclc_soc_device *dev = -		container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev); +	struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;  	struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];  	int ret; @@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)  static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,  			    struct snd_pcm *pcm)  { +	struct platform_device *pdev = to_platform_device(dai->platform->dev); +	struct txx9aclc_soc_device *dev; +	struct resource *r; +	int i; +	int ret; + +	/* at this point onwards the AC97 component has probed and this will be valid */ +	dev = snd_soc_dai_get_drvdata(dai); + +	dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; +	dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; +	for (i = 0; i < 2; i++) { +		r = platform_get_resource(pdev, IORESOURCE_DMA, i); +		if (!r) { +			ret = -EBUSY; +			goto exit; +		} +		dev->dmadata[i].dma_res = r; +		ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); +		if (ret) +			goto exit; +	}  	return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,  		card->dev, 64 * 1024, 4 * 1024 * 1024); + +exit: +	for (i = 0; i < 2; i++) { +		if (dev->dmadata[i].dma_chan) +			dma_release_channel(dev->dmadata[i].dma_chan); +		dev->dmadata[i].dma_chan = NULL; +	} +	return ret;  }  static bool filter(struct dma_chan *chan, void *param) @@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param)  static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,  			     struct txx9aclc_dmadata *dmadata)  { -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;  	struct txx9dmac_slave *ds = &dmadata->dma_slave;  	dma_cap_mask_t mask; @@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,  	dma_cap_set(DMA_SLAVE, mask);  	dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);  	if (!dmadata->dma_chan) { -		dev_err(dev->soc_dev.dev, +		printk(KERN_ERR  			"DMA channel for %s is not available\n",  			dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?  			"playback" : "capture"); @@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,  	return 0;  } -static int txx9aclc_pcm_probe(struct platform_device *pdev) +static int txx9aclc_pcm_probe(struct snd_soc_platform *platform)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct txx9aclc_soc_device *dev = -		container_of(socdev, struct txx9aclc_soc_device, soc_dev); -	struct resource *r; -	int i; -	int ret; - -	dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; -	dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; -	for (i = 0; i < 2; i++) { -		r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i); -		if (!r) { -			ret = -EBUSY; -			goto exit; -		} -		dev->dmadata[i].dma_res = r; -		ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); -		if (ret) -			goto exit; -	} +	snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device);  	return 0; - -exit: -	for (i = 0; i < 2; i++) { -		if (dev->dmadata[i].dma_chan) -			dma_release_channel(dev->dmadata[i].dma_chan); -		dev->dmadata[i].dma_chan = NULL; -	} -	return ret;  } -static int txx9aclc_pcm_remove(struct platform_device *pdev) +static int txx9aclc_pcm_remove(struct snd_soc_platform *platform)  { -	struct snd_soc_device *socdev = platform_get_drvdata(pdev); -	struct txx9aclc_soc_device *dev = -		container_of(socdev, struct txx9aclc_soc_device, soc_dev); -	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); +	struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform); +	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;  	void __iomem *base = drvdata->base;  	int i; @@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev)  	return 0;  } -struct snd_soc_platform txx9aclc_soc_platform = { -	.name		= "txx9aclc-audio", +static struct snd_soc_platform_driver txx9aclc_soc_platform = {  	.probe		= txx9aclc_pcm_probe,  	.remove		= txx9aclc_pcm_remove, -	.pcm_ops 	= &txx9aclc_pcm_ops, +	.ops		= &txx9aclc_pcm_ops,  	.pcm_new	= txx9aclc_pcm_new,  	.pcm_free	= txx9aclc_pcm_free_dma_buffers,  }; -EXPORT_SYMBOL_GPL(txx9aclc_soc_platform); -static int __init txx9aclc_soc_platform_init(void) +static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)  { -	return snd_soc_register_platform(&txx9aclc_soc_platform); +	return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);  } -static void __exit txx9aclc_soc_platform_exit(void) +static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)  { -	snd_soc_unregister_platform(&txx9aclc_soc_platform); +	snd_soc_unregister_platform(&pdev->dev); +	return 0;  } -module_init(txx9aclc_soc_platform_init); -module_exit(txx9aclc_soc_platform_exit); +static struct platform_driver txx9aclc_pcm_driver = { +	.driver = { +			.name = "txx9aclc-pcm-audio", +			.owner = THIS_MODULE, +	}, + +	.probe = txx9aclc_soc_platform_probe, +	.remove = __devexit_p(txx9aclc_soc_platform_remove), +}; + +static int __init snd_txx9aclc_pcm_init(void) +{ +	return platform_driver_register(&txx9aclc_pcm_driver); +} +module_init(snd_txx9aclc_pcm_init); + +static void __exit snd_txx9aclc_pcm_exit(void) +{ +	platform_driver_unregister(&txx9aclc_pcm_driver); +} +module_exit(snd_txx9aclc_pcm_exit);  MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");  MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h index 6769aab41b33..9c2de84fec3b 100644 --- a/sound/soc/txx9/txx9aclc.h +++ b/sound/soc/txx9/txx9aclc.h @@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata {  	u64 physbase;  }; -struct txx9aclc_soc_device { -	struct snd_soc_device soc_dev; -	struct platform_device *aclc_pdev;	/* for ioresources, drvdata */ -	struct txx9aclc_dmadata dmadata[2]; -}; -  static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( -	struct txx9aclc_soc_device *sdev) +	struct snd_soc_dai *dai)  { -	return platform_get_drvdata(sdev->aclc_pdev); +	return dev_get_drvdata(dai->dev);  } -extern struct snd_soc_platform txx9aclc_soc_platform; -extern struct snd_soc_dai txx9aclc_ac97_dai; -  #endif /* __TXX9ACLC_H */  |