diff options
334 files changed, 8543 insertions, 13316 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/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..898430f44f9d 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,90 @@ 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 +2320,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..dbfa05d2cb92 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -31,8 +31,6 @@ #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 +59,12 @@ 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; + void *control_data; +}; + 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 +407,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 +517,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 +534,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 +558,22 @@ 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); + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); + int ret; - if (codec->reg_cache == NULL) - return -ENOMEM; + pr_info("WM8510 Audio Codec %s", WM8510_VERSION); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8510->control_data; + 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 +582,53 @@ 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; - - ret = wm8510_init(socdev, SND_SOC_I2C); - if (ret < 0) - pr_err("failed to initialise WM8510\n"); - - return ret; -} + struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); -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; + + wm8510->control_data = spi; + wm8510->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8510); - ret = wm8510_init(socdev, SND_SOC_SPI); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8510, &wm8510_dai, 1); if (ret < 0) - dev_err(&spi->dev, "failed to initialise WM8510\n"); - + kfree(wm8510); return ret; } static int __devexit wm8510_spi_remove(struct spi_device *spi) { + snd_soc_unregister_codec(&spi->dev); return 0; } @@ -733,84 +643,80 @@ 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_data = i2c; + 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..58d411b6faaf 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,8 @@ 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; + void *control_data; u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; @@ -162,8 +160,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 +384,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 +395,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 +413,21 @@ 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; + codec->control_data = wm8523->control_data; 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 +437,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 +472,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 +481,68 @@ 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_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 +554,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 c3571ee5c11b..cae58941a32f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -199,7 +199,8 @@ 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; + void *control_data; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; @@ -484,9 +485,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 +506,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 +518,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 +585,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 +746,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 +760,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 +772,17 @@ 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); + codec->control_data = wm8580->control_data; + 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 +792,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 +809,69 @@ 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_data = i2c; + 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 +883,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 +894,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 +903,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..8d942b3b111f 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -31,11 +31,10 @@ #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; + void *control_data; u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; }; @@ -163,7 +162,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 +226,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 +337,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 +348,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 +373,24 @@ 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); + codec->control_data = wm8711->control_data; + 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 +399,63 @@ 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->control_data = spi; + 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 +465,31 @@ 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->control_data = client; + 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 +501,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..ae2292444783 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,12 @@ static const u16 wm8728_reg_defaults[] = { 0x100, }; +/* codec private data */ +struct wm8728_priv { + enum snd_soc_control_type control_type; + void *control_data; +}; + static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -96,8 +100,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 +213,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 +224,32 @@ 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); + codec->control_data = wm8728->control_data; + 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 +260,56 @@ 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_data = spi; + 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 +318,81 @@ 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_data = i2c; + 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..7da360ee1fee 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,8 @@ 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; + void *control_data; struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; @@ -222,9 +220,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 +248,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 +259,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 +420,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 +437,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 +457,18 @@ 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, + codec->control_data = wm8731->control_data; - 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 +478,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 +494,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 +505,79 @@ 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_data = spi; + 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 +591,27 @@ 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_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 +623,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 +634,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 +649,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..0c6d59e4d226 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,8 @@ 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; + void *control_data; u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; @@ -145,8 +143,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 +311,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 +322,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 +342,105 @@ 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; + codec->control_data = wm8741->control_data; + 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_data = i2c; + 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 +450,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..89863a5bc830 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -52,7 +52,8 @@ 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; + void *control_data; u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; }; @@ -560,8 +561,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 +649,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 +665,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 +692,22 @@ 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); + codec->control_data = wm8750->control_data; + 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 +731,133 @@ 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_data = spi; + 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_data = i2c; + 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..976e408b3616 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,12 @@ static const u16 wm8753_reg[] = { /* codec private data */ struct wm8753_priv { + enum snd_soc_control_type control_type; + void *control_data; unsigned int sysclk; unsigned int pcmclk; - struct snd_soc_codec codec; u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; + int dai_func; }; /* @@ -228,6 +230,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 +238,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 +906,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 +921,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 +1146,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 +1161,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 +1254,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 +1317,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 +1327,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 +1337,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 +1347,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 +1357,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 +1366,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 +1384,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 +1400,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 +1419,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 +1435,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 +1454,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 +1488,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 +1527,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 +1546,30 @@ 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, + codec->control_data = wm8753->control_data; + 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 +1597,139 @@ 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_data = spi; + 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_data = i2c; + 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..51a2d265d40e 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -31,20 +31,14 @@ #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; + void *control_data; 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 +138,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 +227,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 +261,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 +269,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 +299,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 +351,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 +365,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 +377,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 +410,31 @@ 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; + codec->control_data = wm8776->control_data; + 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 +442,57 @@ 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_data = spi; + 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 +506,27 @@ 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_data = i2c; + 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 +538,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 +549,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..33c3b57f3f66 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,9 @@ #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; + void *control_data; u16 reg_cache[WM8900_MAXREG]; u32 fll_in; /* FLL input frequency */ @@ -627,8 +626,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 +1013,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = { .digital_mute = wm8900_digital_mute, < |