Merge branch 'topic/multi-component' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into for-2.6.37

This commit is contained in:
Mark Brown 2010-08-12 14:40:28 +01:00
commit cf7af01aa7
340 changed files with 9495 additions and 13645 deletions

View File

@ -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] = { struct davinci_timer_instance davinci_timer_instance[2] = {
{ {
.base = DAVINCI_TIMER0_BASE, .base = DAVINCI_TIMER0_BASE,
@ -315,6 +327,7 @@ static int __init davinci_init_devices(void)
/* please keep these calls, and their implementations above, /* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through. * in alphabetical order so they're easier to sort through.
*/ */
davinci_init_pcm();
davinci_init_wdt(); davinci_init_wdt();
return 0; return 0;

View File

@ -732,9 +732,15 @@ static struct platform_device ep93xx_i2s_device = {
.resource = ep93xx_i2s_resource, .resource = ep93xx_i2s_resource,
}; };
static struct platform_device ep93xx_pcm_device = {
.name = "ep93xx-pcm-audio",
.id = -1,
};
void __init ep93xx_register_i2s(void) void __init ep93xx_register_i2s(void)
{ {
platform_device_register(&ep93xx_i2s_device); platform_device_register(&ep93xx_i2s_device);
platform_device_register(&ep93xx_pcm_device);
} }
#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \

View File

@ -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) void __init kirkwood_audio_init(void)
{ {
kirkwood_clk_ctrl |= CGC_AUDIO; kirkwood_clk_ctrl |= CGC_AUDIO;
platform_device_register(&kirkwood_i2s_device); platform_device_register(&kirkwood_i2s_device);
platform_device_register(&kirkwood_pcm_device);
} }
/***************************************************************************** /*****************************************************************************

View File

@ -653,8 +653,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
_REGISTER_CLOCK(NULL, "vpu", vpu_clk) _REGISTER_CLOCK(NULL, "vpu", vpu_clk)
_REGISTER_CLOCK(NULL, "dma", dma_clk) _REGISTER_CLOCK(NULL, "dma", dma_clk)

View File

@ -415,7 +415,7 @@ struct platform_device mxc_usbh2 = {
}; \ }; \
\ \
struct platform_device imx_ssi_device ## n = { \ struct platform_device imx_ssi_device ## n = { \
.name = "imx-ssi", \ .name = "imx-ssi-dai", \
.id = n, \ .id = n, \
.num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \ .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \
.resource = imx_ssi_resources ## n, \ .resource = imx_ssi_resources ## n, \

View File

@ -558,8 +558,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
_REGISTER_CLOCK(NULL, "firi", firi_clk) _REGISTER_CLOCK(NULL, "firi", firi_clk)
_REGISTER_CLOCK(NULL, "ata", ata_clk) _REGISTER_CLOCK(NULL, "ata", ata_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk) _REGISTER_CLOCK(NULL, "rtic", rtic_clk)

View File

@ -464,8 +464,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "sdma", sdma_clk) _REGISTER_CLOCK(NULL, "sdma", sdma_clk)
_REGISTER_CLOCK(NULL, "spba", spba_clk) _REGISTER_CLOCK(NULL, "spba", spba_clk)
_REGISTER_CLOCK(NULL, "spdif", spdif_clk) _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) _REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) _REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)

View File

@ -562,14 +562,14 @@ static struct resource imx_ssi_resources1[] = {
}; };
struct platform_device imx_ssi_device0 = { struct platform_device imx_ssi_device0 = {
.name = "imx-ssi", .name = "imx-ssi-dai",
.id = 0, .id = 0,
.num_resources = ARRAY_SIZE(imx_ssi_resources0), .num_resources = ARRAY_SIZE(imx_ssi_resources0),
.resource = imx_ssi_resources0, .resource = imx_ssi_resources0,
}; };
struct platform_device imx_ssi_device1 = { struct platform_device imx_ssi_device1 = {
.name = "imx-ssi", .name = "imx-ssi-dai",
.id = 1, .id = 1,
.num_resources = ARRAY_SIZE(imx_ssi_resources1), .num_resources = ARRAY_SIZE(imx_ssi_resources1),
.resource = imx_ssi_resources1, .resource = imx_ssi_resources1,

View File

@ -25,6 +25,7 @@
#include <mach/gpio.h> #include <mach/gpio.h>
#include <plat/mmc.h> #include <plat/mmc.h>
#include <plat/omap7xx.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) {} static inline void omap_init_sti(void) {}
#endif #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_rtc();
omap_init_spi100k(); omap_init_spi100k();
omap_init_sti(); omap_init_sti();
omap_init_audio();
return 0; return 0;
} }

View File

@ -20,6 +20,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/usb/musb.h> #include <linux/usb/musb.h>
#include <sound/tlv320aic3x.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -612,11 +613,25 @@ static int n8x0_menelaus_late_init(struct device *dev)
return 0; 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[] = { static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {
{ {
I2C_BOARD_INFO("menelaus", 0x72), I2C_BOARD_INFO("menelaus", 0x72),
.irq = INT_24XX_SYS_NIRQ, .irq = INT_24XX_SYS_NIRQ,
}, },
{
I2C_BOARD_INFO("tlv320aic3x", 0x1b),
.platform_data = &n810_aic33_data,
},
}; };
static struct menelaus_platform_data n8x0_menelaus_platform_data = { static struct menelaus_platform_data n8x0_menelaus_platform_data = {

View File

@ -23,6 +23,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <sound/tlv320aic3x.h>
#include <plat/mcspi.h> #include <plat/mcspi.h>
#include <plat/mux.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 = { static struct twl4030_platform_data rx51_twldata __initdata = {
.irq_base = TWL4030_IRQ_BASE, .irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END, .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[] = { static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
{ {
I2C_BOARD_INFO("tlv320aic3x", 0x18), I2C_BOARD_INFO("tlv320aic3x", 0x18),
.platform_data = &rx51_aic34_data,
}, },
}; };

View File

@ -14,6 +14,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c/twl.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -34,8 +35,11 @@ static void __init omap_zoom2_init_irq(void)
omap_gpio_init(); omap_gpio_init();
} }
/* REVISIT: These audio entries can be removed once MFD code is merged */ /* EXTMUTE callback function */
#if 0 void zoom2_set_hs_extmute(int mute)
{
gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
}
static struct twl4030_madc_platform_data zoom2_madc_data = { static struct twl4030_madc_platform_data zoom2_madc_data = {
.irq_line = 1, .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 = { static struct twl4030_codec_audio_data zoom2_audio_data = {
.audio_mclk = 26000000, .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 = { static struct twl4030_codec_data zoom2_codec_data = {
@ -64,10 +71,24 @@ static struct twl4030_platform_data zoom2_twldata = {
.vmmc1 = &zoom2_vmmc1, .vmmc1 = &zoom2_vmmc1,
.vmmc2 = &zoom2_vmmc2, .vmmc2 = &zoom2_vmmc2,
.vsim = &zoom2_vsim, .vsim = &zoom2_vsim,
}; };
#endif 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,
},
};
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 #ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = { 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); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
zoom_peripherals_init(); zoom_peripherals_init();
omap3_zoom2_i2c_init();
zoom_debugboard_init(); zoom_debugboard_init();
} }

View File

@ -29,6 +29,7 @@
#include <mach/gpio.h> #include <mach/gpio.h>
#include <plat/mmc.h> #include <plat/mmc.h>
#include <plat/dma.h> #include <plat/dma.h>
#include <plat/mcbsp.h>
#include "mux.h" #include "mux.h"
@ -289,6 +290,43 @@ static inline void omap_init_sti(void)
static inline void omap_init_sti(void) {} static inline void omap_init_sti(void) {}
#endif #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) #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
#include <plat/mcspi.h> #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. * in alphabetical order so they're easier to sort through.
*/ */
omap_hsmmc_reset(); omap_hsmmc_reset();
omap_init_audio();
omap_init_camera(); omap_init_camera();
omap_init_mbox(); omap_init_mbox();
omap_init_mcspi(); omap_init_mcspi();

View File

@ -3,3 +3,5 @@
*/ */
extern int __init zoom_debugboard_init(void); extern int __init zoom_debugboard_init(void);
extern void __init zoom_peripherals_init(void); extern void __init zoom_peripherals_init(void);
#define ZOOM2_HEADSET_EXTMUTE_GPIO 153

View File

@ -340,6 +340,31 @@ struct platform_device pxa_device_i2s = {
.num_resources = ARRAY_SIZE(pxai2s_resources), .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; static u64 pxaficp_dmamask = ~(u32)0;
struct platform_device pxa_device_ficp = { struct platform_device pxa_device_ficp = {

View File

@ -37,4 +37,10 @@ extern struct platform_device pxa3xx_device_i2c_power;
extern struct platform_device pxa3xx_device_gcu; 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); void __init pxa_register_device(struct platform_device *dev, void *data);

View File

@ -384,6 +384,10 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
static struct platform_device *devices[] __initdata = { static struct platform_device *devices[] __initdata = {
&pxa27x_device_udc, &pxa27x_device_udc,
&pxa_device_i2s, &pxa_device_i2s,
&pxa_device_asoc_ssp1,
&pxa_device_asoc_ssp2,
&pxa_device_asoc_ssp3,
&pxa_device_asoc_platform,
&sa1100_device_rtc, &sa1100_device_rtc,
&pxa_device_rtc, &pxa_device_rtc,
&pxa27x_device_ssp1, &pxa27x_device_ssp1,

View File

@ -597,6 +597,11 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)
static struct platform_device *devices[] __initdata = { static struct platform_device *devices[] __initdata = {
&pxa27x_device_udc, &pxa27x_device_udc,
&pxa_device_i2s, &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, &sa1100_device_rtc,
&pxa_device_rtc, &pxa_device_rtc,
&pxa27x_device_ssp1, &pxa27x_device_ssp1,

View File

@ -45,6 +45,16 @@ int wm9713_irq;
int lcd_id; int lcd_id;
int lcd_orientation; 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[] = { static struct resource smc91x_resources[] = {
[0] = { [0] = {
.start = ZYLONITE_ETH_PHYS + 0x300, .start = ZYLONITE_ETH_PHYS + 0x300,
@ -408,6 +418,7 @@ static void __init zylonite_init(void)
zylonite_init_nand(); zylonite_init_nand();
zylonite_init_leds(); zylonite_init_leds();
zylonite_init_ohci(); zylonite_init_ohci();
zylonite_init_wm9713_audio();
} }
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")

View File

@ -333,3 +333,16 @@ void __init s3c64xx_ac97_setup_gpio(int num)
else else
s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; 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);

View File

@ -256,6 +256,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_fb, &s3c_device_fb,
&s3c_device_ohci, &s3c_device_ohci,
&s3c_device_usb_hsotg, &s3c_device_usb_hsotg,
&s3c_device_pcm,
&s3c64xx_device_iisv4, &s3c64xx_device_iisv4,
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR

View File

@ -49,9 +49,9 @@ static const char *audmux_port_string(int port)
{ {
switch (port) { switch (port) {
case MX31_AUDMUX_PORT1_SSI0: case MX31_AUDMUX_PORT1_SSI0:
return "imx-ssi.0"; return "imx-ssi-dai.0";
case MX31_AUDMUX_PORT2_SSI1: case MX31_AUDMUX_PORT2_SSI1:
return "imx-ssi.1"; return "imx-ssi-dai.1";
case MX31_AUDMUX_PORT3_SSI_PINS_3: case MX31_AUDMUX_PORT3_SSI_PINS_3:
return "SSI3"; return "SSI3";
case MX31_AUDMUX_PORT4_SSI_PINS_4: case MX31_AUDMUX_PORT4_SSI_PINS_4:

View File

@ -30,6 +30,13 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <plat/clock.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_MCBSP1_BASE 0xfffb1000
#define OMAP7XX_MCBSP2_BASE 0xfffb1800 #define OMAP7XX_MCBSP2_BASE 0xfffb1800

View File

@ -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 = { struct platform_device s3c_device_ac97 = {
.name = "s3c-ac97", .name = "s3c-ac97",
@ -489,11 +489,37 @@ struct platform_device s3c_device_ac97 = {
.num_resources = ARRAY_SIZE(s3c_ac97_resource), .num_resources = ARRAY_SIZE(s3c_ac97_resource),
.resource = s3c_ac97_resource, .resource = s3c_ac97_resource,
.dev = { .dev = {
.dma_mask = &s3c_device_ac97_dmamask, .dma_mask = &s3c_device_audio_dmamask,
.coherent_dma_mask = 0xffffffffUL .coherent_dma_mask = 0xffffffffUL
} }
}; };
EXPORT_SYMBOL(s3c_device_ac97); 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 #endif // CONFIG_CPU_S32440

View File

@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4;
extern struct platform_device s3c64xx_device_spi0; extern struct platform_device s3c64xx_device_spi0;
extern struct platform_device s3c64xx_device_spi1; 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_pcm0;
extern struct platform_device s3c64xx_device_pcm1; extern struct platform_device s3c64xx_device_pcm1;

View File

@ -286,6 +286,7 @@
ssi@16100 { ssi@16100 {
compatible = "fsl,mpc8610-ssi"; compatible = "fsl,mpc8610-ssi";
status = "disabled";
cell-index = <1>; cell-index = <1>;
reg = <0x16100 0x100>; reg = <0x16100 0x100>;
interrupt-parent = <&mpic>; interrupt-parent = <&mpic>;

View File

@ -1,5 +1,5 @@
/** /**
* MPC86xx Internal Memory Map * Freecale 85xx and 86xx Global Utilties register set
* *
* Authors: Jeff Brown * Authors: Jeff Brown
* Timur Tabi <timur@freescale.com> * Timur Tabi <timur@freescale.com>
@ -10,73 +10,112 @@
* under the terms of the GNU General Public License as published by the * 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 * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*
* This header file defines structures for various 86xx SOC devices that are
* used by multiple source files.
*/ */
#ifndef __ASM_POWERPC_IMMAP_86XX_H__ #ifndef __ASM_POWERPC_FSL_GUTS_H__
#define __ASM_POWERPC_IMMAP_86XX_H__ #define __ASM_POWERPC_FSL_GUTS_H__
#ifdef __KERNEL__ #ifdef __KERNEL__
/* Global Utility Registers */ /*
struct ccsr_guts { * These #ifdefs are safe because it's not possible to build a kernel that
* runs on e500 and e600 cores.
*/
#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx)
#error Only 85xx and 86xx SOCs are supported
#endif
/**
* Global Utility Registers.
*
* Not all registers defined in this structure are available on all chips, so
* you are expected to know whether a given register actually exists on your
* chip before you access it.
*
* Also, some registers are similar on different chips but have slightly
* different names. In these cases, one name is chosen to avoid extraneous
* #ifdefs.
*/
#ifdef CONFIG_PPC_85xx
struct ccsr_guts_85xx {
#else
struct ccsr_guts_86xx {
#endif
__be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */
__be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */
__be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */
__be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */
__be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */
u8 res1[0x20 - 0x14]; __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */
u8 res018[0x20 - 0x18];
__be32 porcir; /* 0x.0020 - POR Configuration Information Register */ __be32 porcir; /* 0x.0020 - POR Configuration Information Register */
u8 res2[0x30 - 0x24]; u8 res024[0x30 - 0x24];
__be32 gpiocr; /* 0x.0030 - GPIO Control Register */ __be32 gpiocr; /* 0x.0030 - GPIO Control Register */
u8 res3[0x40 - 0x34]; u8 res034[0x40 - 0x34];
__be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */
u8 res4[0x50 - 0x44]; u8 res044[0x50 - 0x44];
__be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */
u8 res5[0x60 - 0x54]; u8 res054[0x60 - 0x54];
__be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */
u8 res6[0x70 - 0x64]; __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */
__be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */
u8 res06c[0x70 - 0x6c];
__be32 devdisr; /* 0x.0070 - Device Disable Control */ __be32 devdisr; /* 0x.0070 - Device Disable Control */
__be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */
u8 res7[0x80 - 0x78]; u8 res078[0x7c - 0x78];
__be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */
__be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */
u8 res8[0x90 - 0x84]; __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */
__be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */
__be32 pmcdr; /* 0x.008c - 4Power management clock disable register */
__be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */
__be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */
u8 res9[0xA0 - 0x98]; __be32 ectrstcr; /* 0x.0098 - Exception reset control register */
__be32 autorstsr; /* 0x.009c - Automatic reset status register */
__be32 pvr; /* 0x.00a0 - Processor Version Register */ __be32 pvr; /* 0x.00a0 - Processor Version Register */
__be32 svr; /* 0x.00a4 - System Version Register */ __be32 svr; /* 0x.00a4 - System Version Register */
u8 res10[0xB0 - 0xA8]; u8 res0a8[0xb0 - 0xa8];
__be32 rstcr; /* 0x.00b0 - Reset Control Register */ __be32 rstcr; /* 0x.00b0 - Reset Control Register */
u8 res11[0xC0 - 0xB4]; u8 res0b4[0xc0 - 0xb4];
#ifdef CONFIG_PPC_85xx
__be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */
#else
__be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
u8 res12[0x800 - 0xC4]; #endif
u8 res0c4[0x224 - 0xc4];
__be32 iodelay1; /* 0x.0224 - IO delay control register 1 */
__be32 iodelay2; /* 0x.0228 - IO delay control register 2 */
u8 res22c[0x800 - 0x22c];
__be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */
u8 res13[0x900 - 0x804]; u8 res804[0x900 - 0x804];
__be32 ircr; /* 0x.0900 - Infrared Control Register */ __be32 ircr; /* 0x.0900 - Infrared Control Register */
u8 res14[0x908 - 0x904]; u8 res904[0x908 - 0x904];
__be32 dmacr; /* 0x.0908 - DMA Control Register */ __be32 dmacr; /* 0x.0908 - DMA Control Register */
u8 res15[0x914 - 0x90C]; u8 res90c[0x914 - 0x90c];
__be32 elbccr; /* 0x.0914 - eLBC Control Register */ __be32 elbccr; /* 0x.0914 - eLBC Control Register */
u8 res16[0xB20 - 0x918]; u8 res918[0xb20 - 0x918];
__be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */
__be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */
__be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */
u8 res17[0xE00 - 0xB2C]; u8 resb2c[0xe00 - 0xb2c];
__be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */
u8 res18[0xE10 - 0xE04]; u8 rese04[0xe10 - 0xe04];
__be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */
u8 res19[0xE20 - 0xE14]; u8 rese14[0xe20 - 0xe14];
__be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */
u8 res20[0xF04 - 0xE24]; __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */
u8 rese28[0xf04 - 0xe28];
__be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */
__be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */
u8 res21[0xF40 - 0xF0C]; u8 resf0c[0xf2c - 0xf0c];
__be32 srds2cr0; /* 0x.0f40 - SerDes1 Control Register 0 */ __be32 itcr; /* 0x.0f2c - Internal transaction control register */
__be32 srds2cr1; /* 0x.0f44 - SerDes1 Control Register 0 */ u8 resf30[0xf40 - 0xf30];
__be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */
__be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
} __attribute__ ((packed)); } __attribute__ ((packed));
#ifdef CONFIG_PPC_86xx
#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ #define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */
#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ #define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */
@ -93,7 +132,7 @@ struct ccsr_guts {
* ch: The channel on the DMA controller (0, 1, 2, or 3) * ch: The channel on the DMA controller (0, 1, 2, or 3)
* device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
*/ */
static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
unsigned int co, unsigned int ch, unsigned int device) unsigned int co, unsigned int ch, unsigned int device)
{ {
unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
* ch: The channel on the DMA controller (0, 1, 2, or 3) * ch: The channel on the DMA controller (0, 1, 2, or 3)
* value: the new value for the bit (0 or 1) * value: the new value for the bit (0 or 1)
*/ */
static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,
unsigned int co, unsigned int ch, unsigned int value) unsigned int co, unsigned int ch, unsigned int value)
{ {
if ((ch == 0) || (ch == 3)) { if ((ch == 0) || (ch == 3)) {
@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF #define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF
#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ #endif
#endif /* __KERNEL__ */
#endif
#endif

View File

@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = {
.probe = twl4030_vibra_probe, .probe = twl4030_vibra_probe,
.remove = __devexit_p(twl4030_vibra_remove), .remove = __devexit_p(twl4030_vibra_remove),
.driver = { .driver = {
.name = "twl4030_codec_vibra", .name = "twl4030-vibra",
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.pm = &twl4030_vibra_pm_ops, .pm = &twl4030_vibra_pm_ops,
@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void)
} }
module_exit(twl4030_vibra_exit); module_exit(twl4030_vibra_exit);
MODULE_ALIAS("platform:twl4030_codec_vibra"); MODULE_ALIAS("platform:twl4030-vibra");
MODULE_DESCRIPTION("TWL4030 Vibra driver"); MODULE_DESCRIPTION("TWL4030 Vibra driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; 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), pdata->codec, sizeof(*pdata->codec),
false, 0, 0); false, 0, 0);
if (IS_ERR(child)) if (IS_ERR(child))
return PTR_ERR(child); return PTR_ERR(child);
} }
/* Phoenix*/ /* Phoenix codec driver is probed directly atm */
if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; 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), pdata->codec, sizeof(*pdata->codec),
false, 0, 0); false, 0, 0);
if (IS_ERR(child)) if (IS_ERR(child))

View File

@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
if (pdata->audio) { if (pdata->audio) {
cell = &codec->cells[childs]; cell = &codec->cells[childs];
cell->name = "twl4030_codec_audio"; cell->name = "twl4030-codec";
cell->platform_data = pdata->audio; cell->platform_data = pdata->audio;
cell->data_size = sizeof(*pdata->audio); cell->data_size = sizeof(*pdata->audio);
childs++; childs++;
} }
if (pdata->vibra) { if (pdata->vibra) {
cell = &codec->cells[childs]; cell = &codec->cells[childs];
cell->name = "twl4030_codec_vibra"; cell->name = "twl4030-vibra";
cell->platform_data = pdata->vibra; cell->platform_data = pdata->vibra;
cell->data_size = sizeof(*pdata->vibra); cell->data_size = sizeof(*pdata->vibra);
childs++; childs++;
@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev)
return 0; return 0;
} }
MODULE_ALIAS("platform:twl4030_codec"); MODULE_ALIAS("platform:twl4030-audio");
static struct platform_driver twl4030_codec_driver = { static struct platform_driver twl4030_codec_driver = {
.probe = twl4030_codec_probe, .probe = twl4030_codec_probe,
.remove = __devexit_p(twl4030_codec_remove), .remove = __devexit_p(twl4030_codec_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "twl4030_codec", .name = "twl4030-audio",
}, },
}; };

View File

@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
extern int twl4030_remove_script(u8 flags); extern int twl4030_remove_script(u8 flags);
struct twl4030_codec_audio_data { 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 ramp_delay_value;
unsigned int offset_cncl_path;
unsigned int check_defaults:1;
unsigned int reset_registers:1;
unsigned int hs_extmute:1; unsigned int hs_extmute:1;
void (*set_hs_extmute)(int mute); void (*set_hs_extmute)(int mute);
}; };

View File

@ -114,7 +114,7 @@ struct sh_fsi_platform_info {
int (*set_rate)(int is_porta, int rate); /* for master mode */ int (*set_rate)(int is_porta, int rate); /* for master mode */
}; };
extern struct snd_soc_dai fsi_soc_dai[2]; extern struct snd_soc_dai_driver fsi_soc_dai[2];
extern struct snd_soc_platform fsi_soc_platform; extern struct snd_soc_platform_driver fsi_soc_platform;
#endif /* __SOUND_FSI_H */ #endif /* __SOUND_FSI_H */

View File

@ -91,15 +91,17 @@ struct snd_pcm_substream;
SNDRV_PCM_FMTBIT_S32_LE |\ SNDRV_PCM_FMTBIT_S32_LE |\
SNDRV_PCM_FMTBIT_S32_BE) SNDRV_PCM_FMTBIT_S32_BE)
struct snd_soc_dai_ops; struct snd_soc_dai_driver;
struct snd_soc_dai; struct snd_soc_dai;
struct snd_ac97_bus_ops; struct snd_ac97_bus_ops;
/* Digital Audio Interface registration */ /* Digital Audio Interface registration */
int snd_soc_register_dai(struct snd_soc_dai *dai); int snd_soc_register_dai(struct device *dev,
void snd_soc_unregister_dai(struct snd_soc_dai *dai); struct snd_soc_dai_driver *dai_drv);
int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); void snd_soc_unregister_dai(struct device *dev);
void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); int snd_soc_register_dais(struct device *dev,
struct snd_soc_dai_driver *dai_drv, size_t count);
void snd_soc_unregister_dais(struct device *dev, size_t count);
/* Digital Audio Interface clocking API.*/ /* Digital Audio Interface clocking API.*/
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 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 */ /* Digital Audio Interface mute */
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int 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 { struct snd_soc_dai_ops {
/* /*
* DAI clocking configuration, all optional. * 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 */ /* DAI description */
char *name; const char *name;
unsigned int id; unsigned int id;
int ac97_control; int ac97_control;
struct device *dev; /* DAI driver callbacks */
void *ac97_pdata; /* platform_data for the ac97 codec */ int (*probe)(struct snd_soc_dai *dai);
int (*remove)(struct snd_soc_dai *dai);
/* DAI callbacks */
int (*probe)(struct platform_device *pdev,
struct snd_soc_dai *dai);
void (*remove)(struct platform_device *pdev,
struct snd_soc_dai *dai);
int (*suspend)(struct snd_soc_dai *dai); int (*suspend)(struct snd_soc_dai *dai);
int (*resume)(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 capture;
struct snd_soc_pcm_stream playback; struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1; 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 */ /* 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 int active;
unsigned char pop_wait:1; unsigned char pop_wait:1;
unsigned char probed:1;
/* DAI private data */ /* DAI DMA data */
void *private_data; void *playback_dma_data;
void *capture_dma_data;
/* parent platform */ /* parent platform/codec */
struct snd_soc_platform *platform; union {
struct snd_soc_platform *platform;
struct snd_soc_codec *codec;
};
struct snd_soc_card *card;
struct list_head list; struct list_head list;
struct list_head card_list;
}; };
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
const struct snd_pcm_substream *ss) const struct snd_pcm_substream *ss)
{ {
return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 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, 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) void *data)
{ {
if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
dai->playback.dma_data = data; dai->playback_dma_data = data;
else 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 #endif

View File

@ -322,14 +322,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
/* dapm path setup */ /* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); 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, int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
const struct snd_soc_dapm_route *route, int num); const struct snd_soc_dapm_route *route, int num);
/* dapm events */ /* dapm events */
int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
int event); const char *stream, int event);
void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); void snd_soc_dapm_shutdown(struct snd_soc_card *card);
/* dapm sys fs - used by the core */ /* dapm sys fs - used by the core */
int snd_soc_dapm_sys_add(struct device *dev); int snd_soc_dapm_sys_add(struct device *dev);

View File

@ -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_ */

View File

@ -228,13 +228,17 @@ struct snd_soc_ops;
struct snd_soc_dai_mode; struct snd_soc_dai_mode;
struct snd_soc_pcm_runtime; struct snd_soc_pcm_runtime;
struct snd_soc_dai; struct snd_soc_dai;
struct snd_soc_dai_driver;
struct snd_soc_platform; struct snd_soc_platform;
struct snd_soc_dai_link; struct snd_soc_dai_link;
struct snd_soc_platform_driver;
struct snd_soc_codec; struct snd_soc_codec;
struct snd_soc_codec_driver;
struct soc_enum; struct soc_enum;
struct snd_soc_ac97_ops; struct snd_soc_ac97_ops;
struct snd_soc_jack; struct snd_soc_jack;
struct snd_soc_jack_pin; struct snd_soc_jack_pin;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio; struct snd_soc_jack_gpio;
#endif #endif
@ -249,19 +253,18 @@ enum snd_soc_control_type {
SND_SOC_SPI, SND_SOC_SPI,
}; };
int snd_soc_register_platform(struct snd_soc_platform *platform); int snd_soc_register_platform(struct device *dev,
void snd_soc_unregister_platform(struct snd_soc_platform *platform); struct snd_soc_platform_driver *platform_drv);
int snd_soc_register_codec(struct snd_soc_codec *codec); void snd_soc_unregister_platform(struct device *dev);
void snd_soc_unregister_codec(struct snd_soc_codec *codec); int snd_soc_register_codec(struct device *dev,
struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai);
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_volatile_register(struct snd_soc_codec *codec, int reg);
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits, int addr_bits, int data_bits,
enum snd_soc_control_type control); 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 */ /* 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_calc_frame_size(int sample_size, int channels, int tdm_slots);
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); 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); const struct snd_pcm_hardware *hw);
/* Jack reporting */ /* 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); struct snd_soc_jack *jack);
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); 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, 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_soc_jack {
struct snd_jack *jack; struct snd_jack *jack;
struct snd_soc_card *card; struct snd_soc_codec *codec;
struct list_head pins; struct list_head pins;
int status; int status;
struct blocking_notifier_head notifier; struct blocking_notifier_head notifier;
@ -398,15 +401,13 @@ struct snd_soc_jack {
/* SoC PCM stream information */ /* SoC PCM stream information */
struct snd_soc_pcm_stream { struct snd_soc_pcm_stream {
char *stream_name; const char *stream_name;
u64 formats; /* SNDRV_PCM_FMTBIT_* */ u64 formats; /* SNDRV_PCM_FMTBIT_* */
unsigned int rates; /* SNDRV_PCM_RATE_* */ unsigned int rates; /* SNDRV_PCM_RATE_* */
unsigned int rate_min; /* min rate */ unsigned int rate_min; /* min rate */
unsigned int rate_max; /* max rate */ unsigned int rate_max; /* max rate */
unsigned int channels_min; /* min channels */ unsigned int channels_min; /* min channels */
unsigned int channels_max; /* max channels */ unsigned int channels_max; /* max channels */
unsigned int active; /* stream is in use */
void *dma_data; /* used by platform code */
}; };
/* SoC audio ops */ /* SoC audio ops */
@ -419,44 +420,35 @@ struct snd_soc_ops {
int (*trigger)(struct snd_pcm_substream *, int); int (*trigger)(struct snd_pcm_substream *, int);
}; };
/* SoC Audio Codec */ /* SoC Audio Codec device */
struct snd_soc_codec { struct snd_soc_codec {
char *name; const char *name;
struct module *owner; int id;
struct mutex mutex;
struct device *dev; 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; struct list_head list;
struct list_head card_list;
/* callbacks */ int num_dai;
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
/* runtime */ /* runtime */
struct snd_card *card;
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
unsigned int active; unsigned int active;
unsigned int pcm_devs;
void *drvdata;
/* 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 idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
unsigned int cache_only:1; /* Suppress writes to hardware */ unsigned int cache_only:1; /* Suppress writes to hardware */
unsigned int cache_sync:1; /* Cache needs to be synced 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 */
hw_write_t hw_write;
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
void *reg_cache;
/* dapm */ /* dapm */
u32 pop_time; u32 pop_time;
@ -466,10 +458,6 @@ struct snd_soc_codec {
enum snd_soc_bias_level suspend_bias_level; enum snd_soc_bias_level suspend_bias_level;
struct delayed_work delayed_work; struct delayed_work delayed_work;
/* codec DAI's */
struct snd_soc_dai *dai;
unsigned int num_dai;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_codec_root; struct dentry *debugfs_codec_root;
struct dentry *debugfs_reg; struct dentry *debugfs_reg;
@ -478,23 +466,40 @@ struct snd_soc_codec {
#endif #endif
}; };
/* codec device */ /* codec driver */
struct snd_soc_codec_device { struct snd_soc_codec_driver {
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev); /* driver ops */
int (*suspend)(struct platform_device *pdev, pm_message_t state); int (*probe)(struct snd_soc_codec *);
int (*resume)(struct platform_device *pdev); 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 */ /* SoC platform interface */
struct snd_soc_platform { struct snd_soc_platform_driver {
char *name;
struct list_head list;
int (*probe)(struct platform_device *pdev); int (*probe)(struct snd_soc_platform *);
int (*remove)(struct platform_device *pdev); int (*remove)(struct snd_soc_platform *);
int (*suspend)(struct snd_soc_dai_link *dai_link); int (*suspend)(struct snd_soc_dai *dai);
int (*resume)(struct snd_soc_dai_link *dai_link); int (*resume)(struct snd_soc_dai *dai);
/* pcm creation and destruction */ /* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@ -509,23 +514,31 @@ struct snd_soc_platform {
struct snd_soc_dai *); struct snd_soc_dai *);
/* platform stream ops */ /* 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_platform {
struct snd_soc_dai_link { const char *name;
char *name; /* Codec name */ int id;
char *stream_name; /* Stream name */ struct device *dev;
struct snd_soc_platform_driver *driver;
/* DAI */ unsigned int suspended:1; /* platform is suspended */
struct snd_soc_dai *codec_dai; unsigned int probed:1;
struct snd_soc_dai *cpu_dai;
/* machine stream operations */ struct snd_soc_card *card;
struct snd_soc_ops *ops; struct list_head list;
struct list_head card_list;
};
/* codec/machine specific init - e.g. add machine controls */ struct snd_soc_dai_link {
int (*init)(struct snd_soc_codec *codec); /* 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 */ /* Keep DAI active over suspend */
unsigned int ignore_suspend:1; unsigned int ignore_suspend:1;
@ -533,21 +546,24 @@ struct snd_soc_dai_link {
/* Symmetry requirements */ /* Symmetry requirements */
unsigned int symmetric_rates:1; unsigned int symmetric_rates:1;
/* Symmetry data - only valid if symmetry is being enforced */ /* codec/machine specific init - e.g. add machine controls */
unsigned int rate; int (*init)(struct snd_soc_pcm_runtime *rtd);
/* DAI pcm */ /* machine stream operations */
struct snd_pcm *pcm; struct snd_soc_ops *ops;
}; };
/* SoC card */ /* SoC card */
struct snd_soc_card { struct snd_soc_card {
char *name; const char *name;
struct device *dev; struct device *dev;
struct snd_card *snd_card;
struct module *owner;
struct list_head list; struct list_head list;
struct mutex mutex;
int instantiated; bool instantiated;
int (*probe)(struct platform_device *pdev); int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev); int (*remove)(struct platform_device *pdev);
@ -568,28 +584,38 @@ struct snd_soc_card {
/* CPU <--> Codec DAI links */ /* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
int num_links; 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; 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 */ /* SoC machine DAI configuration, glues a codec and cpu DAI together */
struct snd_soc_device { struct snd_soc_pcm_runtime {
struct device *dev; struct device dev;
struct snd_soc_card *card; struct snd_soc_card *card;
struct snd_soc_codec_device *codec_dev; struct snd_soc_dai_link *dai_link;
void *codec_data;
};
/* runtime channel data */ unsigned int complete:1;
struct snd_soc_pcm_runtime { unsigned int dev_registered:1;
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 */ /* mixer control */
@ -615,24 +641,48 @@ struct soc_enum {
static inline unsigned int snd_soc_read(struct snd_soc_codec *codec, static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,
unsigned int reg) 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, static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int val) 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, 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) 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> #include <sound/soc-dai.h>

View File

@ -10,8 +10,49 @@
#ifndef __TLV320AIC3x_H__ #ifndef __TLV320AIC3x_H__
#define __TLV320AIC3x_H__ #define __TLV320AIC3x_H__
struct aic3x_pdata { /* GPIO API */
int gpio_reset; /* < 0 if not used */ 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
}; };
#endif 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

View File

@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params); 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->params->dma_intr_handler = atmel_pcm_dma_irq;
prtd->dma_buffer = runtime->dma_addr; 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) if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = 0xffffffff; card->dev->coherent_dma_mask = 0xffffffff;
if (dai->playback.channels_min) { if (dai->driver->playback.channels_min) {
ret = atmel_pcm_preallocate_dma_buffer(pcm, ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK); SNDRV_PCM_STREAM_PLAYBACK);
if (ret) if (ret)
goto out; goto out;
} }
if (dai->capture.channels_min) { if (dai->driver->capture.channels_min) {
pr_debug("at32-pcm:" pr_debug("at32-pcm:"
"Allocating PCM capture DMA buffer\n"); "Allocating PCM capture DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm, 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 #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_runtime *runtime = dai->runtime;
struct snd_pcm_str *stream = &pcm->streams[0];
struct snd_pcm_substream *substream = stream->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd; struct atmel_runtime_data *prtd;
struct atmel_pcm_dma_params *params; struct atmel_pcm_dma_params *params;
@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
return 0; 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_runtime *runtime = dai->runtime;
struct snd_pcm_str *stream = &pcm->streams[0];
struct snd_pcm_substream *substream = stream->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd; struct atmel_runtime_data *prtd;
struct atmel_pcm_dma_params *params; 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 #define atmel_pcm_resume NULL
#endif #endif
struct snd_soc_platform atmel_soc_platform = { static struct snd_soc_platform_driver atmel_soc_platform = {
.name = "atmel-audio", .ops = &atmel_pcm_ops,
.pcm_ops = &atmel_pcm_ops,
.pcm_new = atmel_pcm_new, .pcm_new = atmel_pcm_new,
.pcm_free = atmel_pcm_free_dma_buffers, .pcm_free = atmel_pcm_free_dma_buffers,
.suspend = atmel_pcm_suspend, .suspend = atmel_pcm_suspend,
.resume = atmel_pcm_resume, .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(&atmel_soc_platform); return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
} }
module_init(atmel_pcm_modinit);
static void __exit atmel_pcm_modexit(void) static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_platform(&atmel_soc_platform); snd_soc_unregister_platform(&pdev->dev);
return 0;
} }
module_exit(atmel_pcm_modexit);
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 platform_driver_register(&atmel_pcm_driver);
}
module_init(snd_atmel_pcm_init);
static void __exit snd_atmel_pcm_exit(void)
{
platform_driver_unregister(&atmel_pcm_driver);
}
module_exit(snd_atmel_pcm_exit);
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("Atmel PCM module"); MODULE_DESCRIPTION("Atmel PCM module");

View File

@ -74,9 +74,6 @@ struct atmel_pcm_dma_params {
void (*dma_intr_handler)(u32, struct snd_pcm_substream *); 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) * SSC register access (since ssc_writel() / ssc_readl() require literal name)
*/ */

View File

@ -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, static int atmel_ssc_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
int dir_mask; int dir_mask;
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", 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, static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
struct atmel_pcm_dma_params *dma_params; struct atmel_pcm_dma_params *dma_params;
int dir, dir_mask; 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_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 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_ssc_info *ssc_p = &ssc_info[id];
struct atmel_pcm_dma_params *dma_params; struct atmel_pcm_dma_params *dma_params;
int dir, channels, bits; 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 * function. It should not be used for other purposes
* as it is common to all substreams. * 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); 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, static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
struct atmel_pcm_dma_params *dma_params; struct atmel_pcm_dma_params *dma_params;
int dir; int dir;
@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
# define atmel_ssc_resume NULL # define atmel_ssc_resume NULL
#endif /* CONFIG_PM */ #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) #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, .set_clkdiv = atmel_ssc_set_dai_clkdiv,
}; };
struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
{ .name = "atmel-ssc0", {
.id = 0, .name = "atmel-ssc-dai.0",
.probe = atmel_ssc_probe,
.remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend, .suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume, .resume = atmel_ssc_resume,
.playback = { .playback = {
@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES, .rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops, .ops = &atmel_ssc_dai_ops,
.private_data = &ssc_info[0],
}, },
#if NUM_SSC_DEVICES == 3 #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, .suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume, .resume = atmel_ssc_resume,
.playback = { .playback = {
@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES, .rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops, .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, .suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume, .resume = atmel_ssc_resume,
.playback = { .playback = {
@ -756,23 +783,43 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES, .rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops, .ops = &atmel_ssc_dai_ops,
.private_data = &ssc_info[2],
}, },
#endif #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(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); return snd_soc_register_dais(&pdev->dev, atmel_ssc_dai,
ARRAY_SIZE(atmel_ssc_dai));
} }
module_init(atmel_ssc_modinit);
static void __exit atmel_ssc_modexit(void) static int __devexit asoc_ssc_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(atmel_ssc_dai));
return 0;
} }
module_exit(atmel_ssc_modexit);
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 platform_driver_register(&asoc_ssc_driver);
}
module_init(snd_atmel_ssc_init);
static void __exit snd_atmel_ssc_exit(void)
{
platform_driver_unregister(&asoc_ssc_driver);
}
module_exit(snd_atmel_ssc_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");

View File

@ -116,6 +116,5 @@ struct atmel_ssc_info {
struct atmel_pcm_dma_params *dma_params[2]; struct atmel_pcm_dma_params *dma_params[2];
struct atmel_ssc_state ssc_state; struct atmel_ssc_state ssc_state;
}; };
extern struct snd_soc_dai atmel_ssc_dai[];
#endif /* _AT91_SSC_DAI_H */ #endif /* _AT91_SSC_DAI_H */

View File

@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai) 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_device *ssc = ssc_p->ssc;
struct ssc_clock_data cd; struct ssc_clock_data cd;
unsigned int rate, width_bits, channels; 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_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->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_device *ssc = ssc_p->ssc;
unsigned int pll_out = 0, bclk = 0, mclk_div = 0; unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
int ret; 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; int i;
/* /*
@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
/* Make CSB show PLL rate */ /* 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); WM8510_OPCLKDIV_1 | 4);
return 0; 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 = { static struct snd_soc_dai_link playpaq_wm8510_dai = {
.name = "WM8510", .name = "WM8510",
.stream_name = "WM8510 PCM", .stream_name = "WM8510 PCM",
.cpu_dai = &at32_ssc_dai[0], .cpu_dai_name= "atmel-ssc-dai.0",
.codec_dai = &wm8510_dai, .platform_name = "atmel-pcm-audio",
.codec_name = "wm8510-codec.0-0x1a",
.codec_dai_name = "wm8510-hifi",
.init = playpaq_wm8510_init, .init = playpaq_wm8510_init,
.ops = &playpaq_wm8510_ops, .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 = { static struct snd_soc_card snd_soc_playpaq = {
.name = "LRS_PlayPaq_WM8510", .name = "LRS_PlayPaq_WM8510",
.platform = &at32_soc_platform,
.dai_link = &playpaq_wm8510_dai, .dai_link = &playpaq_wm8510_dai,
.num_links = 1, .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 struct platform_device *playpaq_snd_device;
static int __init playpaq_asoc_init(void) static int __init playpaq_asoc_init(void)
{ {
int ret = 0; 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 * Configure MCLK for WM8510
@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void)
goto err_device_alloc; goto err_device_alloc;
} }
platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata); platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
ret = platform_device_add(playpaq_snd_device); ret = platform_device_add(playpaq_snd_device);
if (ret) { if (ret) {
@ -468,25 +440,12 @@ err_pll0:
clk_put(_gclk0); clk_put(_gclk0);
_gclk0 = NULL; _gclk0 = NULL;
} }
err_gclk0:
ssc_free(ssc);
err_ssc:
return ret; return ret;
} }
static void __exit playpaq_asoc_exit(void) 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) { if (_gclk0 != NULL) {
clk_put(_gclk0); clk_put(_gclk0);
_gclk0 = NULL; _gclk0 = NULL;

View File

@ -69,8 +69,8 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret; int ret;
/* set codec DAI configuration */ /* 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. * 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; int ret;
printk(KERN_DEBUG 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 = { static struct snd_soc_dai_link at91sam9g20ek_dai = {
.name = "WM8731", .name = "WM8731",
.stream_name = "WM8731 PCM", .stream_name = "WM8731 PCM",
.cpu_dai = &atmel_ssc_dai[0], .cpu_dai_name = "atmel-ssc-dai.0",
.codec_dai = &wm8731_dai, .codec_dai_name = "wm8731-hifi",
.init = at91sam9g20ek_wm8731_init, .init = at91sam9g20ek_wm8731_init,
.platform_name = "atmel_pcm-audio",
.codec_name = "wm8731-codec.0-001a",
.ops = &at91sam9g20ek_ops, .ops = &at91sam9g20ek_ops,
}; };
static struct snd_soc_card snd_soc_at91sam9g20ek = { static struct snd_soc_card snd_soc_at91sam9g20ek = {
.name = "AT91SAMG20-EK", .name = "AT91SAMG20-EK",
.platform = &atmel_soc_platform,
.dai_link = &at91sam9g20ek_dai, .dai_link = &at91sam9g20ek_dai,
.num_links = 1, .num_links = 1,
.set_bias_level = at91sam9g20ek_set_bias_level, .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 struct platform_device *at91sam9g20ek_snd_device;
static int __init at91sam9g20ek_init(void) 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; struct clk *pllb;
int ret; int ret;
@ -235,18 +230,6 @@ static int __init at91sam9g20ek_init(void)
clk_set_rate(mclk, MCLK_RATE); 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); at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
if (!at91sam9g20ek_snd_device) { if (!at91sam9g20ek_snd_device) {
printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 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, platform_set_drvdata(at91sam9g20ek_snd_device,
&at91sam9g20ek_snd_devdata); &snd_soc_at91sam9g20ek);
at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
ret = platform_device_add(at91sam9g20ek_snd_device); ret = platform_device_add(at91sam9g20ek_snd_device);
if (ret) { if (ret) {
@ -265,9 +247,6 @@ static int __init at91sam9g20ek_init(void)
return ret; return ret;
err_ssc:
ssc_free(ssc);
ssc_p->ssc = NULL;
err_mclk: err_mclk:
clk_put(mclk); clk_put(mclk);
mclk = NULL; mclk = NULL;
@ -277,16 +256,6 @@ err:
static void __exit at91sam9g20ek_exit(void) 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); platform_device_unregister(at91sam9g20ek_snd_device);
at91sam9g20ek_snd_device = NULL; at91sam9g20ek_snd_device = NULL;
clk_put(mclk); clk_put(mclk);

View File

@ -46,8 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err; int err;
/* Set codec DAI configuration */ /* Set codec DAI configuration */
@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"MICIN", NULL, "Mic Jack"}, {"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 */ /* Add afeb9260 specific widgets */
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_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 = { static struct snd_soc_dai_link afeb9260_dai = {
.name = "TLV320AIC23", .name = "TLV320AIC23",
.stream_name = "AIC23", .stream_name = "AIC23",
.cpu_dai = &atmel_ssc_dai[0], .cpu_dai_name = "atmel-ssc-dai.0",
.codec_dai = &tlv320aic23_dai, .codec_dai_name = "tlv320aic23-hifi",
.platform_name = "atmel_pcm-audio",
.codec_name = "tlv320aic23-codec.0-0x1a",
.init = afeb9260_tlv320aic23_init, .init = afeb9260_tlv320aic23_init,
.ops = &afeb9260_ops, .ops = &afeb9260_ops,
}; };
@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = {
/* Audio machine driver */ /* Audio machine driver */
static struct snd_soc_card snd_soc_machine_afeb9260 = { static struct snd_soc_card snd_soc_machine_afeb9260 = {
.name = "AFEB9260", .name = "AFEB9260",
.platform = &atmel_soc_platform,
.dai_link = &afeb9260_dai, .dai_link = &afeb9260_dai,
.num_links = 1, .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 struct platform_device *afeb9260_snd_device;
static int __init afeb9260_soc_init(void) static int __init afeb9260_soc_init(void)
{ {
int err; int err;
struct device *dev; struct device *dev;
struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data;
struct ssc_device *ssc = NULL;
if (!(machine_is_afeb9260())) if (!(machine_is_afeb9260()))
return -ENODEV; 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); afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
if (!afeb9260_snd_device) { if (!afeb9260_snd_device) {
@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void)
return -ENOMEM; return -ENOMEM;
} }
platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata); platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);
afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev;
err = platform_device_add(afeb9260_snd_device); err = platform_device_add(afeb9260_snd_device);
if (err) if (err)
goto err1; goto err1;
@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void)
err1: err1:
platform_device_del(afeb9260_snd_device); platform_device_del(afeb9260_snd_device);
platform_device_put(afeb9260_snd_device); platform_device_put(afeb9260_snd_device);
err_ssc:
return err; return err;
} }
static void __exit afeb9260_soc_exit(void) static void __exit afeb9260_soc_exit(void)

View File

@ -19,7 +19,6 @@
#include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-db1x00/bcsr.h> #include <asm/mach-db1x00/bcsr.h>
#include "../codecs/ac97.h"
#include "../codecs/wm8731.h" #include "../codecs/wm8731.h"
#include "psc.h" #include "psc.h"
@ -28,20 +27,16 @@
static struct snd_soc_dai_link db1200_ac97_dai = { static struct snd_soc_dai_link db1200_ac97_dai = {
.name = "AC97", .name = "AC97",
.stream_name = "AC97 HiFi", .stream_name = "AC97 HiFi",
.cpu_dai = &au1xpsc_ac97_dai, .cpu_dai_name = "au1xpsc-ac97",
.codec_dai = &ac97_dai, .codec_dai_name = "ac97-hifi",
.platform_name = "au1xpsc-pcm-audio",
.codec_name = "ac97-codec",
}; };
static struct snd_soc_card db1200_ac97_machine = { static struct snd_soc_card db1200_ac97_machine = {
.name = "DB1200_AC97", .name = "DB1200_AC97",
.dai_link = &db1200_ac97_dai, .dai_link = &db1200_ac97_dai,
.num_links = 1, .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 ---------------------------*/ /*------------------------- I2S PART ---------------------------*/
@ -49,8 +44,8 @@ static struct snd_soc_device db1200_ac97_devdata = {
static int db1200_i2s_startup(struct snd_pcm_substream *substream) static int db1200_i2s_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret; int ret;
/* WM8731 has its own 12MHz crystal */ /* 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 = { static struct snd_soc_dai_link db1200_i2s_dai = {
.name = "WM8731", .name = "WM8731",
.stream_name = "WM8731 PCM", .stream_name = "WM8731 PCM",
.cpu_dai = &au1xpsc_i2s_dai, .cpu_dai_name = "au1xpsc",
.codec_dai = &wm8731_dai, .codec_dai_name = "wm8731-hifi"
.platform_name = "au1xpsc-pcm-audio",
.codec_name = "wm8731-codec.0-001a",
.ops = &db1200_i2s_wm8731_ops, .ops = &db1200_i2s_wm8731_ops,
}; };
@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = {
.name = "DB1200_I2S", .name = "DB1200_I2S",
.dai_link = &db1200_i2s_dai, .dai_link = &db1200_i2s_dai,
.num_links = 1, .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 ---------------------------*/ /*------------------------- COMMON PART ---------------------------*/
@ -112,12 +103,10 @@ static int __init db1200_audio_load(void)
/* DB1200 board setup set PSC1MUX to preferred audio device */ /* DB1200 board setup set PSC1MUX to preferred audio device */
if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) 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 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); ret = platform_device_add(db1200_asoc_dev);
if (ret) { if (ret) {

View File

@ -329,7 +329,7 @@ static int au1xpsc_pcm_new(struct snd_card *card,
return 0; 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]) if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
return -ENODEV; return -ENODEV;
@ -337,17 +337,10 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int au1xpsc_pcm_remove(struct platform_device *pdev)
{
return 0;
}
/* au1xpsc audio platform */ /* au1xpsc audio platform */
struct snd_soc_platform au1xpsc_soc_platform = { struct snd_soc_platform_driver au1xpsc_soc_platform = {
.name = "au1xpsc-pcm-dbdma",
.probe = au1xpsc_pcm_probe, .probe = au1xpsc_pcm_probe,
.remove = au1xpsc_pcm_remove, .ops = &au1xpsc_pcm_ops,
.pcm_ops = &au1xpsc_pcm_ops,
.pcm_new = au1xpsc_pcm_new, .pcm_new = au1xpsc_pcm_new,
.pcm_free = au1xpsc_pcm_free_dma_buffers, .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; (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) if (!ret)
return ret; return ret;
@ -404,7 +397,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
{ {
int i; int i;
snd_soc_unregister_platform(&au1xpsc_soc_platform); snd_soc_unregister_platform(&pdev->dev);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (au1xpsc_audio_pcmdma[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 = { static struct platform_driver au1xpsc_pcm_driver = {
.driver = { .driver = {
.name = "au1xpsc-pcm", .name = "au1xpsc-pcm-audio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = au1xpsc_pcm_drvprobe, .probe = au1xpsc_pcm_drvprobe,

View File

@ -315,27 +315,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int au1xpsc_ac97_probe(struct platform_device *pdev, static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
return au1xpsc_ac97_workdata ? 0 : -ENODEV; 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 = { static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
.trigger = au1xpsc_ac97_trigger, .trigger = au1xpsc_ac97_trigger,
.hw_params = au1xpsc_ac97_hw_params, .hw_params = au1xpsc_ac97_hw_params,
}; };
struct snd_soc_dai au1xpsc_ac97_dai = { struct snd_soc_dai_driver au1xpsc_ac97_dai = {
.name = "au1xpsc_ac97",
.ac97_control = 1, .ac97_control = 1,
.probe = au1xpsc_ac97_probe, .probe = au1xpsc_ac97_probe,
.remove = au1xpsc_ac97_remove,
.playback = { .playback = {
.rates = AC97_RATES, .rates = AC97_RATES,
.formats = AC97_FMTS, .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_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
au_sync(); au_sync();
ret = snd_soc_register_dai(&au1xpsc_ac97_dai); ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai);
if (ret) if (ret)
goto out1; goto out1;
@ -406,7 +398,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
return 0; return 0;
} }
snd_soc_unregister_dai(&au1xpsc_ac97_dai); snd_soc_unregister_dai(&pdev->dev);
out1: out1:
release_mem_region(r->start, resource_size(r)); release_mem_region(r->start, resource_size(r));
out0: out0:
@ -422,7 +414,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
if (wd->dmapd) if (wd->dmapd)
au1xpsc_pcm_destroy(wd->dmapd); au1xpsc_pcm_destroy(wd->dmapd);
snd_soc_unregister_dai(&au1xpsc_ac97_dai); snd_soc_unregister_dai(&pdev->dev);
/* disable PSC completely */ /* disable PSC completely */
au_writel(0, AC97_CFG(wd)); au_writel(0, AC97_CFG(wd));
@ -485,7 +477,7 @@ static struct dev_pm_ops au1xpscac97_pmops = {
static struct platform_driver au1xpsc_ac97_driver = { static struct platform_driver au1xpsc_ac97_driver = {
.driver = { .driver = {
.name = "au1xpsc_ac97", .name = "au1xpsc-ac97",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = AU1XPSCAC97_PMOPS, .pm = AU1XPSCAC97_PMOPS,
}, },

View File

@ -263,27 +263,19 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int au1xpsc_i2s_probe(struct platform_device *pdev, static int au1xpsc_i2s_probe(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
return au1xpsc_i2s_workdata ? 0 : -ENODEV; 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 = { static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
.trigger = au1xpsc_i2s_trigger, .trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params, .hw_params = au1xpsc_i2s_hw_params,
.set_fmt = au1xpsc_i2s_set_fmt, .set_fmt = au1xpsc_i2s_set_fmt,
}; };
struct snd_soc_dai au1xpsc_i2s_dai = { static struct snd_soc_dai_driver au1xpsc_i2s_dai = {
.name = "au1xpsc_i2s",
.probe = au1xpsc_i2s_probe, .probe = au1xpsc_i2s_probe,
.remove = au1xpsc_i2s_remove,
.playback = { .playback = {
.rates = AU1XPSC_I2S_RATES, .rates = AU1XPSC_I2S_RATES,
.formats = AU1XPSC_I2S_FMTS, .formats = AU1XPSC_I2S_FMTS,
@ -298,7 +290,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
}, },
.ops = &au1xpsc_i2s_dai_ops, .ops = &au1xpsc_i2s_dai_ops,
}; };
EXPORT_SYMBOL(au1xpsc_i2s_dai);
static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) 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. * time out.
*/ */
ret = snd_soc_register_dai(&au1xpsc_i2s_dai); ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai);
if (ret) if (ret)
goto out1; goto out1;
@ -358,7 +349,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
return 0; return 0;
} }
snd_soc_unregister_dai(&au1xpsc_i2s_dai); snd_soc_unregister_dai(&pdev->dev);
out1: out1:
release_mem_region(r->start, resource_size(r)); release_mem_region(r->start, resource_size(r));
out0: out0:
@ -374,7 +365,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
if (wd->dmapd) if (wd->dmapd)
au1xpsc_pcm_destroy(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_writel(0, I2S_CFG(wd));
au_sync(); au_sync();
@ -436,7 +427,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = {
static struct platform_driver au1xpsc_i2s_driver = { static struct platform_driver au1xpsc_i2s_driver = {
.driver = { .driver = {
.name = "au1xpsc_i2s", .name = "au1xpsc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = AU1XPSCI2S_PMOPS, .pm = AU1XPSCI2S_PMOPS,
}, },

View File

@ -16,9 +16,6 @@
#ifndef _AU1X_PCM_H #ifndef _AU1X_PCM_H
#define _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; extern struct snd_ac97_bus_ops soc_ac97_ops;
/* DBDMA helpers */ /* DBDMA helpers */

View File

@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
if (!card->dev->coherent_dma_mask) if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 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, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK); SNDRV_PCM_STREAM_PLAYBACK);
if (ret) if (ret)
goto out; goto out;
} }
if (dai->capture.channels_min) { if (dai->driver->capture.channels_min) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE); SNDRV_PCM_STREAM_CAPTURE);
if (ret) if (ret)
@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
return ret; return ret;
} }
struct snd_soc_platform bf5xx_ac97_soc_platform = { static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
.name = "bf5xx-audio", .ops = &bf5xx_pcm_ac97_ops,
.pcm_ops = &bf5xx_pcm_ac97_ops,
.pcm_new = bf5xx_pcm_ac97_new, .pcm_new = bf5xx_pcm_ac97_new,
.pcm_free = bf5xx_pcm_free_dma_buffers, .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;
} }
module_exit(bfin_ac97_exit);
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(snd_bf5xx_pcm_exit);
MODULE_AUTHOR("Cliff Cai"); MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");

View File

@ -23,7 +23,4 @@ struct bf5xx_gpio {
u32 frm; u32 frm;
}; };
/* platform data */
extern struct snd_soc_platform bf5xx_ac97_soc_platform;
#endif #endif

View File

@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) 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); pr_debug("%s : sport %d\n", __func__, dai->id);
if (!dai->active) 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) static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
{ {
int ret; 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); pr_debug("%s : sport %d\n", __func__, dai->id);
if (!dai->active) if (!dai->active)
@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
#define bf5xx_ac97_resume NULL #define bf5xx_ac97_resume NULL
#endif #endif
static int bf5xx_ac97_probe(struct platform_device *pdev, static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
int ret = 0; int ret = 0;
cmd_count = (int *)get_zeroed_page(GFP_KERNEL); cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
@ -379,8 +378,7 @@ peripheral_err:
return ret; return ret;
} }
static void bf5xx_ac97_remove(struct platform_device *pdev, static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
free_page((unsigned long)cmd_count); free_page((unsigned long)cmd_count);
cmd_count = NULL; cmd_count = NULL;
@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif #endif
return 0;
} }
struct snd_soc_dai bfin_ac97_dai = { struct snd_soc_dai_driver bfin_ac97_dai = {
.name = "bf5xx-ac97",
.id = 0,
.ac97_control = 1, .ac97_control = 1,
.probe = bf5xx_ac97_probe, .probe = bf5xx_ac97_probe,
.remove = bf5xx_ac97_remove, .remove = bf5xx_ac97_remove,
@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = {
}; };
EXPORT_SYMBOL_GPL(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) 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); module_init(bfin_ac97_init);
static void __exit bfin_ac97_exit(void) 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_exit(bfin_ac97_exit);
MODULE_AUTHOR("Roy Huang"); MODULE_AUTHOR("Roy Huang");
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -50,8 +50,6 @@ struct ac97_frame {
#define TAG_PCM_SR 0x0080 #define TAG_PCM_SR 0x0080
#define TAG_PCM_LFE 0x0040 #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, \ void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
size_t count, unsigned int chan_mask); size_t count, unsigned int chan_mask);

View File

@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836;
static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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; 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_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
int ret = 0; int ret = 0;
/* set cpu DAI configuration */ /* 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 = { static struct snd_soc_dai_link bf5xx_ad1836_dai = {
.name = "ad1836", .name = "ad1836",
.stream_name = "AD1836", .stream_name = "AD1836",
.cpu_dai = &bf5xx_tdm_dai, .cpu_dai_name = "bf5xx-tdm",
.codec_dai = &ad1836_dai, .codec_dai_name = "ad1836-hifi",
.platform_name = "bf5xx-tdm-pcm-audio",
.codec_name = "ad1836-codec.0",
.ops = &bf5xx_ad1836_ops, .ops = &bf5xx_ad1836_ops,
}; };
static struct snd_soc_card bf5xx_ad1836 = { static struct snd_soc_card bf5xx_ad1836 = {
.name = "bf5xx_ad1836", .name = "bf5xx_ad1836",
.platform = &bf5xx_tdm_soc_platform,
.dai_link = &bf5xx_ad1836_dai, .dai_link = &bf5xx_ad1836_dai,
.num_links = 1, .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 struct platform_device *bfxx_ad1836_snd_device;
static int __init bf5xx_ad1836_init(void) static int __init bf5xx_ad1836_init(void)
@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void)
if (!bfxx_ad1836_snd_device) if (!bfxx_ad1836_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836);
bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev;
ret = platform_device_add(bfxx_ad1836_snd_device); ret = platform_device_add(bfxx_ad1836_snd_device);
if (ret) if (ret)

View File

@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x;
static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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; 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_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
int ret = 0; int ret = 0;
/* set cpu DAI configuration */ /* 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 = { static struct snd_soc_dai_link bf5xx_ad193x_dai = {
.name = "ad193x", .name = "ad193x",
.stream_name = "AD193X", .stream_name = "AD193X",
.cpu_dai = &bf5xx_tdm_dai, .cpu_dai_name = "bf5xx-tdm",
.codec_dai = &ad193x_dai, .codec_dai_name ="ad193x-hifi",
.platform_name = "bf5xx-tdm-pcm-audio",
.codec_name = "ad193x-codec.5",
.ops = &bf5xx_ad193x_ops, .ops = &bf5xx_ad193x_ops,
}; };
static struct snd_soc_card bf5xx_ad193x = { static struct snd_soc_card bf5xx_ad193x = {
.name = "bf5xx_ad193x", .name = "bf5xx_ad193x",
.platform = &bf5xx_tdm_soc_platform,
.dai_link = &bf5xx_ad193x_dai, .dai_link = &bf5xx_ad193x_dai,
.num_links = 1, .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 struct platform_device *bfxx_ad193x_snd_device;
static int __init bf5xx_ad193x_init(void) static int __init bf5xx_ad193x_init(void)
@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void)
if (!bfxx_ad193x_snd_device) if (!bfxx_ad193x_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata); platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x);
bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
ret = platform_device_add(bfxx_ad193x_snd_device); ret = platform_device_add(bfxx_ad193x_snd_device);
if (ret) if (ret)

View File

@ -48,10 +48,10 @@ static struct snd_soc_card bf5xx_board;
static int bf5xx_board_startup(struct snd_pcm_substream *substream) static int bf5xx_board_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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__); pr_debug("%s enter\n", __func__);
cpu_dai->private_data = sport_handle; snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
return 0; return 0;
} }
@ -62,23 +62,19 @@ static struct snd_soc_ops bf5xx_board_ops = {
static struct snd_soc_dai_link bf5xx_board_dai = { static struct snd_soc_dai_link bf5xx_board_dai = {
.name = "AC97", .name = "AC97",
.stream_name = "AC97 HiFi", .stream_name = "AC97 HiFi",
.cpu_dai = &bfin_ac97_dai, .cpu_dai_name = "bfin-ac97",
.codec_dai = &ad1980_dai, .codec_dai_name = "ad1980-hifi",
.platform_name = "bfin-pcm-audio",
.codec_name = "ad1980-codec",
.ops = &bf5xx_board_ops, .ops = &bf5xx_board_ops,
}; };
static struct snd_soc_card bf5xx_board = { static struct snd_soc_card bf5xx_board = {
.name = "bf5xx-board", .name = "bf5xx-board",
.platform = &bf5xx_ac97_soc_platform,
.dai_link = &bf5xx_board_dai, .dai_link = &bf5xx_board_dai,
.num_links = 1, .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 struct platform_device *bf5xx_board_snd_device;
static int __init bf5xx_board_init(void) static int __init bf5xx_board_init(void)
@ -89,8 +85,7 @@ static int __init bf5xx_board_init(void)
if (!bf5xx_board_snd_device) if (!bf5xx_board_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata); platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board);
bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev;
ret = platform_device_add(bf5xx_board_snd_device); ret = platform_device_add(bf5xx_board_snd_device);
if (ret) if (ret)

View File

@ -47,7 +47,6 @@
#include "../codecs/ad73311.h" #include "../codecs/ad73311.h"
#include "bf5xx-sport.h" #include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h" #include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
#if CONFIG_SND_BF5XX_SPORT_NUM == 0 #if CONFIG_SND_BF5XX_SPORT_NUM == 0
#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 #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) static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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__); pr_debug("%s enter\n", __func__);
cpu_dai->private_data = sport_handle; snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
return 0; 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_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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; int ret = 0;
pr_debug("%s rate %d format %x\n", __func__, params_rate(params), 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 = { static struct snd_soc_dai_link bf5xx_ad73311_dai = {
.name = "ad73311", .name = "ad73311",
.stream_name = "AD73311", .stream_name = "AD73311",
.cpu_dai = &bf5xx_i2s_dai, .cpu_dai_name = "bf5xx-i2s",
.codec_dai = &ad73311_dai, .codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-pcm-audio",
.codec_name = "ad73311-codec",
.ops = &bf5xx_ad73311_ops, .ops = &bf5xx_ad73311_ops,
}; };
static struct snd_soc_card bf5xx_ad73311 = { static struct snd_soc_card bf5xx_ad73311 = {
.name = "bf5xx_ad73311", .name = "bf5xx_ad73311",
.platform = &bf5xx_i2s_soc_platform,
.probe = bf5xx_probe, .probe = bf5xx_probe,
.dai_link = &bf5xx_ad73311_dai, .dai_link = &bf5xx_ad73311_dai,
.num_links = 1, .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 struct platform_device *bf5xx_ad73311_snd_device;
static int __init bf5xx_ad73311_init(void) static int __init bf5xx_ad73311_init(void)
@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void)
if (!bf5xx_ad73311_snd_device) if (!bf5xx_ad73311_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311);
bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
ret = platform_device_add(bf5xx_ad73311_snd_device); ret = platform_device_add(bf5xx_ad73311_snd_device);
if (ret) if (ret)

View File

@ -40,7 +40,6 @@
#include <asm/dma.h> #include <asm/dma.h>
#include "bf5xx-i2s-pcm.h" #include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
#include "bf5xx-sport.h" #include "bf5xx-sport.h"
static void bf5xx_dma_irq(void *data) 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) if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 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, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK); SNDRV_PCM_STREAM_PLAYBACK);
if (ret) if (ret)
goto out; goto out;
} }
if (dai->capture.channels_min) { if (dai->driver->capture.channels_min) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE); SNDRV_PCM_STREAM_CAPTURE);
if (ret) if (ret)
@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
return ret; return ret;
} }
struct snd_soc_platform bf5xx_i2s_soc_platform = { static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
.name = "bf5xx-audio", .ops = &bf5xx_pcm_i2s_ops,
.pcm_ops = &bf5xx_pcm_i2s_ops,
.pcm_new = bf5xx_pcm_i2s_new, .pcm_new = bf5xx_pcm_i2s_new,
.pcm_free = bf5xx_pcm_free_dma_buffers, .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;
} }
module_exit(bfin_i2s_exit);
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(snd_bfin_i2s_pcm_exit);
MODULE_AUTHOR("Cliff Cai"); MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");

View File

@ -23,7 +23,4 @@ struct bf5xx_gpio {
u32 frm; u32 frm;
}; };
/* platform data */
extern struct snd_soc_platform bf5xx_i2s_soc_platform;
#endif #endif

View File

@ -42,7 +42,6 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include "bf5xx-sport.h" #include "bf5xx-sport.h"
#include "bf5xx-i2s.h"
struct bf5xx_i2s_port { struct bf5xx_i2s_port {
u16 tcr1; u16 tcr1;
@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
bf5xx_i2s.configured = 0; bf5xx_i2s.configured = 0;
} }
static int bf5xx_i2s_probe(struct platform_device *pdev, static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
pr_debug("%s enter\n", __func__); pr_debug("%s enter\n", __func__);
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 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; return 0;
} }
static void bf5xx_i2s_remove(struct platform_device *pdev, static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
pr_debug("%s enter\n", __func__); pr_debug("%s enter\n", __func__);
peripheral_free_list(&sport_req[sport_num][0]); peripheral_free_list(&sport_req[sport_num][0]);
return 0;
} }
#ifdef CONFIG_PM #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); pr_debug("%s : sport %d\n", __func__, dai->id);
if (dai->capture.active) if (dai->capture_active)
sport_rx_stop(sport_handle); sport_rx_stop(sport_handle);
if (dai->playback.active) if (dai->playback_active)
sport_tx_stop(sport_handle); sport_tx_stop(sport_handle);
return 0; return 0;
} }
@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
.set_fmt = bf5xx_i2s_set_dai_fmt, .set_fmt = bf5xx_i2s_set_dai_fmt,
}; };
struct snd_soc_dai bf5xx_i2s_dai = { static struct snd_soc_dai_driver bf5xx_i2s_dai = {
.name = "bf5xx-i2s",
.id = 0,
.probe = bf5xx_i2s_probe, .probe = bf5xx_i2s_probe,
.remove = bf5xx_i2s_remove, .remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend, .suspend = bf5xx_i2s_suspend,
@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = {
.formats = BF5XX_I2S_FORMATS,}, .formats = BF5XX_I2S_FORMATS,},
.ops = &bf5xx_i2s_dai_ops, .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) 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) 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_exit(bfin_i2s_exit);
/* Module information */ /* Module information */

View File

@ -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

View File

@ -42,17 +42,16 @@
#include "../codecs/ssm2602.h" #include "../codecs/ssm2602.h"
#include "bf5xx-sport.h" #include "bf5xx-sport.h"
#include "bf5xx-i2s-pcm.h" #include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
static struct snd_soc_card bf5xx_ssm2602; static struct snd_soc_card bf5xx_ssm2602;
static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; 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__); pr_debug("%s enter\n", __func__);
cpu_dai->private_data = sport_handle; snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
return 0; 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_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int clk = 0; unsigned int clk = 0;
int ret = 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 = { static struct snd_soc_dai_link bf5xx_ssm2602_dai = {
.name = "ssm2602", .name = "ssm2602",
.stream_name = "SSM2602", .stream_name = "SSM2602",
.cpu_dai = &bf5xx_i2s_dai, .cpu_dai_name = "bf5xx-i2s",
.codec_dai = &ssm2602_dai, .codec_dai_name = "ssm2602-hifi",
.platform_name = "bf5xx-pcm-audio",
.codec_name = "ssm2602-codec.0-0x1b",
.ops = &bf5xx_ssm2602_ops, .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 = { static struct snd_soc_card bf5xx_ssm2602 = {
.name = "bf5xx_ssm2602", .name = "bf5xx_ssm2602",
.platform = &bf5xx_i2s_soc_platform,
.dai_link = &bf5xx_ssm2602_dai, .dai_link = &bf5xx_ssm2602_dai,
.num_links = 1, .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 struct platform_device *bf5xx_ssm2602_snd_device;
static int __init bf5xx_ssm2602_init(void) static int __init bf5xx_ssm2602_init(void)
@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void)
if (!bf5xx_ssm2602_snd_device) if (!bf5xx_ssm2602_snd_device)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(bf5xx_ssm2602_snd_device, platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602);
&bf5xx_ssm2602_snd_devdata);
bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
ret = platform_device_add(bf5xx_ssm2602_snd_device); ret = platform_device_add(bf5xx_ssm2602_snd_device);
if (ret) if (ret)

View File

@ -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) if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 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, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK); SNDRV_PCM_STREAM_PLAYBACK);
if (ret) if (ret)
goto out; goto out;
} }
if (dai->capture.channels_min) { if (dai->driver->capture.channels_min) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm, ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE); SNDRV_PCM_STREAM_CAPTURE);
if (ret) if (ret)
@ -307,25 +307,44 @@ out:
return ret; return ret;
} }
struct snd_soc_platform bf5xx_tdm_soc_platform = { static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
.name = "bf5xx-audio", .ops = &bf5xx_pcm_tdm_ops,
.pcm_ops = &bf5xx_pcm_tdm_ops,
.pcm_new = bf5xx_pcm_tdm_new, .pcm_new = bf5xx_pcm_tdm_new,
.pcm_free = bf5xx_pcm_free_dma_buffers, .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;
} }
module_exit(bfin_pcm_tdm_exit);
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(snd_bfin_tdm_exit);
MODULE_AUTHOR("Barry Song"); MODULE_AUTHOR("Barry Song");
MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");

View File

@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params {
char *name; /* stream identifier */ char *name; /* stream identifier */
}; };
/* platform data */
extern struct snd_soc_platform bf5xx_tdm_soc_platform;
#endif #endif

View File

@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
if (!dai->active) if (!dai->active)
return 0; return 0;
if (dai->capture.active) if (dai->capture_active)
sport_rx_stop(sport); sport_rx_stop(sport);
if (dai->playback.active) if (dai->playback_active)
sport_tx_stop(sport); sport_tx_stop(sport);
return 0; 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) static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
{ {
int ret; int ret;
struct sport_device *sport = dai->private_data; struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
if (!dai->active) if (!dai->active)
return 0; return 0;
@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
.set_channel_map = bf5xx_tdm_set_channel_map, .set_channel_map = bf5xx_tdm_set_channel_map,
}; };
struct snd_soc_dai bf5xx_tdm_dai = { static struct snd_soc_dai_driver bf5xx_tdm_dai = {
.name = "bf5xx-tdm",
.id = 0,
.suspend = bf5xx_tdm_suspend, .suspend = bf5xx_tdm_suspend,
.resume = bf5xx_tdm_resume, .resume = bf5xx_tdm_resume,
.playback = { .playback = {
@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,}, .formats = SNDRV_PCM_FMTBIT_S32_LE,},
.ops = &bf5xx_tdm_dai_ops, .ops = &bf5xx_tdm_dai_ops,
}; };
EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
static int __devinit bfin_tdm_probe(struct platform_device *pdev) 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; goto sport_config_err;
} }
ret = snd_soc_register_dai(&bf5xx_tdm_dai); ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
if (ret) { if (ret) {
pr_err("Failed to register DAI: %d\n", ret); pr_err("Failed to register DAI: %d\n", ret);
goto sport_config_err; goto sport_config_err;
@ -337,7 +334,7 @@ sport_config_err:
static int __devexit bfin_tdm_remove(struct platform_device *pdev) static int __devexit bfin_tdm_remove(struct platform_device *pdev)
{ {
peripheral_free_list(&sport_req[sport_num][0]); peripheral_free_list(&sport_req[sport_num][0]);
snd_soc_unregister_dai(&bf5xx_tdm_dai); snd_soc_unregister_dai(&pdev->dev);
return 0; return 0;
} }

View File

@ -20,6 +20,4 @@ struct bf5xx_tdm_port {
int configured; int configured;
}; };
extern struct snd_soc_dai bf5xx_tdm_dai;
#endif #endif

View File

@ -21,7 +21,6 @@
#include <sound/ac97_codec.h> #include <sound/ac97_codec.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "ac97.h"
#define AC97_VERSION "0.6" #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_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; 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, .prepare = ac97_prepare,
}; };
struct snd_soc_dai ac97_dai = { static struct snd_soc_dai_driver ac97_dai = {
.name = "AC97 HiFi", .name = "ac97-hifi",
.ac97_control = 1, .ac97_control = 1,
.playback = { .playback = {
.stream_name = "AC97 Playback", .stream_name = "AC97 Playback",
@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = {
.formats = SND_SOC_STD_AC97_FMTS,}, .formats = SND_SOC_STD_AC97_FMTS,},
.ops = &ac97_dai_ops, .ops = &ac97_dai_ops,
}; };
EXPORT_SYMBOL_GPL(ac97_dai);
static unsigned int ac97_read(struct snd_soc_codec *codec, static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg) unsigned int reg)
@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0; 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_bus *ac97_bus;
struct snd_ac97_template ac97_template; struct snd_ac97_template ac97_template;
int i; int ret;
int ret = 0;
printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (!socdev->card->codec) if (ret < 0) {
return -ENOMEM; printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n");
codec = socdev->card->codec; return ret;
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;
/* add codec as bus device for standard ac97 */ /* 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) if (ret < 0)
goto bus_err; return ret;
memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
if (ret < 0) if (ret < 0)
goto bus_err; return ret;
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 0; 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; return 0;
} }
#ifdef CONFIG_PM #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(codec->ac97);
snd_ac97_suspend(socdev->card->codec->ac97);
return 0; 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(codec->ac97);
snd_ac97_resume(socdev->card->codec->ac97);
return 0; return 0;
} }
@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev)
#define ac97_soc_resume NULL #define ac97_soc_resume NULL
#endif #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, .probe = ac97_soc_probe,
.remove = ac97_soc_remove, .remove = ac97_soc_remove,
.suspend = ac97_soc_suspend, .suspend = ac97_soc_suspend,
.resume = ac97_soc_resume, .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_DESCRIPTION("Soc Generic AC97 driver");
MODULE_AUTHOR("Liam Girdwood"); MODULE_AUTHOR("Liam Girdwood");

View File

@ -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

View File

@ -33,15 +33,10 @@
/* codec private data */ /* codec private data */
struct ad1836_priv { struct ad1836_priv {
struct snd_soc_codec codec; enum snd_soc_control_type control_type;
u16 reg_cache[AD1836_NUM_REGS]; 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 * 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; int word_len = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
/* bit size */ /* bit size */
switch (params_format(params)) { switch (params_format(params)) {
@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
} }
#ifdef CONFIG_PM #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) 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 */ /* reset clock control mode */
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 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); 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 */ /* restore clock control mode */
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
adc_ctrl2 |= AD1836_ADC_AUX; adc_ctrl2 |= AD1836_ADC_AUX;
@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
#define ad1836_soc_resume NULL #define ad1836_soc_resume NULL
#endif #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 = { static struct snd_soc_dai_ops ad1836_dai_ops = {
.hw_params = ad1836_hw_params, .hw_params = ad1836_hw_params,
.set_fmt = ad1836_set_dai_fmt, .set_fmt = ad1836_set_dai_fmt,
}; };
/* codec DAI instance */ /* codec DAI instance */
struct snd_soc_dai ad1836_dai = { static struct snd_soc_dai_driver ad1836_dai = {
.name = "AD1836", .name = "ad1836-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 2, .channels_min = 2,
@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
}, },
.ops = &ad1836_dai_ops, .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 ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_codec *codec = &ad1836->codec; int ret = 0;
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;
codec->control_data = ad1836->control_data;
ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "failed to set cache I/O: %d\n", 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_L3_VOL, 0x3FF);
snd_soc_write(codec, AD1836_DAC_R3_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, snd_soc_add_controls(codec, ad1836_snd_controls,
ARRAY_SIZE(ad1836_snd_controls)); ARRAY_SIZE(ad1836_snd_controls));
snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
ARRAY_SIZE(ad1836_dapm_widgets)); ARRAY_SIZE(ad1836_dapm_widgets));
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
pcm_err:
return ret; return ret;
} }
/* power down chip */ /* 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); /* reset clock control mode */
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
snd_soc_free_pcms(socdev); return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
snd_soc_dapm_free(socdev);
return 0;
} }
struct snd_soc_codec_device soc_codec_dev_ad1836 = { static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
.probe = ad1836_probe, .probe = ad1836_probe,
.remove = ad1836_remove, .remove = ad1836_remove,
.suspend = ad1836_soc_suspend, .suspend = ad1836_soc_suspend,
.resume = ad1836_soc_resume, .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) static int __init ad1836_init(void)
{ {

View File

@ -60,6 +60,4 @@
#define AD1836_NUM_REGS 16 #define AD1836_NUM_REGS 16
extern struct snd_soc_dai ad1836_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad1836;
#endif #endif

View File

@ -24,9 +24,10 @@
/* codec private data */ /* codec private data */
struct ad193x_priv { struct ad193x_priv {
unsigned int sysclk;
struct snd_soc_codec codec;
u8 reg_cache[AD193X_NUM_REGS]; u8 reg_cache[AD193X_NUM_REGS];
enum snd_soc_control_type bus_type;
void *control_data;
int sysclk;
}; };
/* ad193x register cache & default register settings */ /* 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, 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 * 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; int word_len = 0, reg = 0, master_rate = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
/* bit size */ /* bit size */
@ -323,46 +320,46 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) static struct snd_soc_dai_ops ad193x_dai_ops = {
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
.set_tdm_slot = ad193x_set_tdm_slot,
.set_sysclk = ad193x_set_dai_sysclk,
.set_fmt = ad193x_set_dai_fmt,
};
/* codec DAI instance */
static struct snd_soc_dai_driver ad193x_dai = {
.name = "ad193x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 4,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &ad193x_dai_ops,
};
static int ad193x_probe(struct snd_soc_codec *codec)
{ {
struct snd_soc_codec *codec; struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
struct ad193x_priv *ad193x;
int ret; int ret;
if (ad193x_codec) { codec->control_data = ad193x->control_data;
dev_err(dev, "Another ad193x is registered\n"); if (ad193x->bus_type == SND_SOC_I2C)
return -EINVAL; ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type);
}
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 else
ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "failed to set cache I/O: %d\n", dev_err(codec->dev, "failed to set cache I/O: %d\n",
ret); ret);
@ -385,89 +382,6 @@ static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
/* pll input: mclki/xi */ /* 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_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); 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,
.set_tdm_slot = ad193x_set_tdm_slot,
.set_sysclk = ad193x_set_dai_sysclk,
.set_fmt = ad193x_set_dai_fmt,
};
/* codec DAI instance */
struct snd_soc_dai ad193x_dai = {
.name = "AD193X",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 4,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &ad193x_dai_ops,
};
EXPORT_SYMBOL_GPL(ad193x_dai);
static int ad193x_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
int ret = 0;
if (ad193x_codec == NULL) {
dev_err(&pdev->dev, "Codec device not registered\n");
return -ENODEV;
}
socdev->card->codec = ad193x_codec;
codec = ad193x_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, ad193x_snd_controls, snd_soc_add_controls(codec, ad193x_snd_controls,
ARRAY_SIZE(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)); ARRAY_SIZE(ad193x_dapm_widgets));
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
pcm_err:
return ret; return ret;
} }
/* power down chip */ static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
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 = {
.probe = ad193x_probe, .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) #if defined(CONFIG_SPI_MASTER)
static int __devinit ad193x_spi_probe(struct spi_device *spi) 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) 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 = { static struct spi_driver ad193x_spi_driver = {
.driver = { .driver = {
.name = "ad193x", .name = "ad193x-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = ad193x_spi_probe, .probe = ad193x_spi_probe,
@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);
static int __devinit ad193x_i2c_probe(struct i2c_client *client, static int __devinit ad193x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) 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) 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 = { static struct i2c_driver ad193x_i2c_driver = {
.driver = { .driver = {
.name = "ad193x", .name = "ad193x-codec",
}, },
.probe = ad193x_i2c_probe, .probe = ad193x_i2c_probe,
.remove = __devexit_p(ad193x_i2c_remove), .remove = __devexit_p(ad193x_i2c_remove),

View File

@ -80,7 +80,4 @@
#define AD193X_NUM_REGS 17 #define AD193X_NUM_REGS 17
extern struct snd_soc_dai ad193x_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad193x;
#endif #endif

View File

@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0; return 0;
} }
struct snd_soc_dai ad1980_dai = { struct snd_soc_dai_driver ad1980_dai = {
.name = "AC97", .name = "ad1980-hifi",
.ac97_control = 1, .ac97_control = 1,
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
@ -177,53 +177,20 @@ err:
return -EIO; 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); int ret;
struct snd_soc_codec *codec;
int ret = 0;
u16 vendor_id2; u16 vendor_id2;
u16 ext_status; u16 ext_status;
printk(KERN_INFO "AD1980 SoC Audio Codec\n"); 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); ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); 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); ret = ad1980_reset(codec, 0);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); 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; return 0;
reset_err: reset_err:
snd_soc_free_pcms(socdev);
pcm_err:
snd_soc_free_ac97_codec(codec); snd_soc_free_ac97_codec(codec);
codec_err:
kfree(codec->reg_cache);
cache_err:
kfree(socdev->card->codec);
socdev->card->codec = NULL;
return ret; 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); snd_soc_free_ac97_codec(codec);
kfree(codec->reg_cache);
kfree(codec);
return 0; 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, .probe = ad1980_soc_probe,
.remove = ad1980_soc_remove, .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_DESCRIPTION("ASoC ad1980 driver");
MODULE_AUTHOR("Roy Huang, Cliff Cai"); MODULE_AUTHOR("Roy Huang, Cliff Cai");

View File

@ -17,7 +17,4 @@
#define PR5 0x2000 #define PR5 0x2000
#define PR6 0x4000 #define PR6 0x4000
extern struct snd_soc_dai ad1980_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad1980;
#endif #endif

View File

@ -23,8 +23,8 @@
#include "ad73311.h" #include "ad73311.h"
struct snd_soc_dai ad73311_dai = { static struct snd_soc_dai_driver ad73311_dai = {
.name = "AD73311", .name = "ad73311-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {
.rates = SNDRV_PCM_RATE_8000, .rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, }, .formats = SNDRV_PCM_FMTBIT_S16_LE, },
}; };
EXPORT_SYMBOL_GPL(ad73311_dai);
static int ad73311_soc_probe(struct platform_device *pdev) static struct snd_soc_codec_driver soc_codec_dev_ad73311;
static int ad73311_probe(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); return snd_soc_register_codec(&pdev->dev,
struct snd_soc_codec *codec; &soc_codec_dev_ad73311, &ad73311_dai, 1);
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;
pcm_err:
kfree(socdev->card->codec);
socdev->card->codec = NULL;
return ret;
} }
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); snd_soc_unregister_codec(&pdev->dev);
struct snd_soc_codec *codec = socdev->card->codec;
if (codec == NULL)
return 0;
snd_soc_free_pcms(socdev);
kfree(codec);
return 0; return 0;
} }
struct snd_soc_codec_device soc_codec_dev_ad73311 = { static struct platform_driver ad73311_codec_driver = {
.probe = ad73311_soc_probe, .driver = {
.remove = ad73311_soc_remove, .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) static int __init ad73311_init(void)
{ {
return snd_soc_register_dai(&ad73311_dai); return platform_driver_register(&ad73311_codec_driver);
} }
module_init(ad73311_init); module_init(ad73311_init);
static void __exit ad73311_exit(void) static void __exit ad73311_exit(void)
{ {
snd_soc_unregister_dai(&ad73311_dai); platform_driver_unregister(&ad73311_codec_driver);
} }
module_exit(ad73311_exit); module_exit(ad73311_exit);

View File

@ -85,6 +85,4 @@
#define REGF_INV (1 << 6) #define REGF_INV (1 << 6)
#define REGF_ALB (1 << 7) #define REGF_ALB (1 << 7)
extern struct snd_soc_dai ad73311_dai;
extern struct snd_soc_codec_device soc_codec_dev_ad73311;
#endif #endif

View File

@ -19,16 +19,12 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "ads117x.h"
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
struct snd_soc_dai ads117x_dai = { static struct snd_soc_dai_driver ads117x_dai = {
/* ADC */ /* ADC */
.name = "ADS117X ADC", .name = "ads117x-hifi",
.id = 1,
.capture = { .capture = {
.stream_name = "Capture", .stream_name = "Capture",
.channels_min = 1, .channels_min = 1,
@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {
.rates = ADS117X_RATES, .rates = ADS117X_RATES,
.formats = ADS117X_FORMATS,}, .formats = ADS117X_FORMATS,},
}; };
EXPORT_SYMBOL_GPL(ads117x_dai);
static int ads117x_probe(struct platform_device *pdev) static struct snd_soc_codec_driver soc_codec_dev_ads117x;
static __devinit int ads117x_probe(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); return snd_soc_register_codec(&pdev->dev,
struct snd_soc_codec *codec; &soc_codec_dev_ads117x, &ads117x_dai, 1);
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) static int __devexit ads117x_remove(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); snd_soc_unregister_codec(&pdev->dev);
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 __devinit int ads117x_platform_probe(struct platform_device *pdev)
{
ads117x_dai.dev = &pdev->dev;
return snd_soc_register_dai(&ads117x_dai);
}
static int __devexit ads117x_platform_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&ads117x_dai);
return 0; return 0;
} }
static struct platform_driver ads117x_codec_driver = { static struct platform_driver ads117x_codec_driver = {
.driver = { .driver = {
.name = "ads117x", .name = "ads117x-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = ads117x_platform_probe, .probe = ads117x_probe,
.remove = __devexit_p(ads117x_platform_remove), .remove = __devexit_p(ads117x_remove),
}; };
static int __init ads117x_init(void) static int __init ads117x_init(void)

View File

@ -9,5 +9,5 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*/ */
extern struct snd_soc_dai ads117x_dai; extern struct snd_soc_dai_driver ads117x_dai;
extern struct snd_soc_codec_device soc_codec_dev_ads117x; extern struct snd_soc_codec_driver soc_codec_dev_ads117x;

View File

@ -17,8 +17,6 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <sound/asoundef.h> #include <sound/asoundef.h>
#include "ak4104.h"
/* AK4104 registers addresses */ /* AK4104 registers addresses */
#define AK4104_REG_CONTROL1 0x00 #define AK4104_REG_CONTROL1 0x00
#define AK4104_REG_RESERVED 0x01 #define AK4104_REG_RESERVED 0x01
@ -45,11 +43,11 @@
#define AK4104_TX_TXE (1 << 0) #define AK4104_TX_TXE (1 << 0)
#define AK4104_TX_V (1 << 1) #define AK4104_TX_V (1 << 1)
#define DRV_NAME "ak4104" #define DRV_NAME "ak4104-codec"
struct ak4104_private { struct ak4104_private {
struct snd_soc_codec codec; enum snd_soc_control_type control_type;
u8 reg_cache[AK4104_NUM_REGS]; void *control_data;
}; };
static int ak4104_fill_cache(struct snd_soc_codec *codec) 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; u8 *reg_cache = codec->reg_cache;
struct spi_device *spi = codec->control_data; 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); int ret = spi_w8r8(spi, i | AK4104_READ);
if (ret < 0) { if (ret < 0) {
dev_err(&spi->dev, "SPI write failure\n"); 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; u8 *reg_cache = codec->reg_cache;
if (reg >= codec->reg_cache_size) if (reg >= codec->driver->reg_cache_size)
return -EINVAL; return -EINVAL;
return reg_cache[reg]; 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; u8 *cache = codec->reg_cache;
struct spi_device *spi = codec->control_data; struct spi_device *spi = codec->control_data;
if (reg >= codec->reg_cache_size) if (reg >= codec->driver->reg_cache_size)
return -EINVAL; return -EINVAL;
/* only write to the hardware if value has changed */ /* 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_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
int val = 0; int val = 0;
/* set the IEC958 bits: consumer mode, no copyright bit */ /* 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, .set_fmt = ak4104_set_dai_fmt,
}; };
struct snd_soc_dai ak4104_dai = { static struct snd_soc_dai_driver ak4104_dai = {
.name = DRV_NAME, .name = "ak4104-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 2, .channels_min = 2,
@ -192,13 +189,71 @@ struct snd_soc_dai ak4104_dai = {
.ops = &ak4101_dai_ops, .ops = &ak4101_dai_ops,
}; };
static struct snd_soc_codec *ak4104_codec; static int ak4104_probe(struct snd_soc_codec *codec)
{
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
int ret, val;
codec->control_data = ak4104->control_data;
/* read all regs and fill the cache */
ret = ak4104_fill_cache(codec);
if (ret < 0) {
dev_err(codec->dev, "failed to fill register cache\n");
return ret;
}
/* read the 'reserved' register - according to the datasheet, it
* should contain 0x5b. Not a good way to verify the presence of
* the device, but there is no hardware ID register. */
if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
AK4104_RESERVED_VAL)
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)
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)
return ret;
dev_info(codec->dev, "SPI device initialized\n");
return 0;
}
static int ak4104_remove(struct snd_soc_codec *codec)
{
int val, ret;
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(codec, AK4104_REG_CONTROL1, val);
return ret;
}
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) static int ak4104_spi_probe(struct spi_device *spi)
{ {
struct snd_soc_codec *codec;
struct ak4104_private *ak4104; struct ak4104_private *ak4104;
int ret, val; int ret;
spi->bits_per_word = 8; spi->bits_per_word = 8;
spi->mode = SPI_MODE_0; spi->mode = SPI_MODE_0;
@ -207,125 +262,27 @@ static int ak4104_spi_probe(struct spi_device *spi)
return ret; return ret;
ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
if (!ak4104) { if (ak4104 == NULL)
dev_err(&spi->dev, "could not allocate codec\n");
return -ENOMEM; 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;
/* read all regs and fill the cache */
ret = ak4104_fill_cache(codec);
if (ret < 0) {
dev_err(&spi->dev, "failed to fill register cache\n");
return ret;
}
/* read the 'reserved' register - according to the datasheet, it
* should contain 0x5b. Not a good way to verify the presence of
* the device, but there is no hardware ID register. */
if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
AK4104_RESERVED_VAL) {
ret = -ENODEV;
goto error_free_codec;
}
/* set power-up and non-reset bits */
val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
if (ret < 0)
goto error_free_codec;
/* enable transmitter */
val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
val |= AK4104_TX_TXE;
ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
if (ret < 0)
goto error_free_codec;
ak4104_codec = codec;
ret = snd_soc_register_dai(&ak4104_dai);
if (ret < 0) {
dev_err(&spi->dev, "failed to register DAI\n");
goto error_free_codec;
}
ak4104->control_data = spi;
ak4104->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, ak4104); spi_set_drvdata(spi, ak4104);
dev_info(&spi->dev, "SPI device initialized\n");
return 0;
error_free_codec: ret = snd_soc_register_codec(&spi->dev,
kfree(ak4104); &soc_codec_device_ak4104, &ak4104_dai, 1);
ak4104_dai.dev = NULL; if (ret < 0)
kfree(ak4104);
return ret; return ret;
} }
static int __devexit ak4104_spi_remove(struct spi_device *spi) static int __devexit ak4104_spi_remove(struct spi_device *spi)
{ {
int ret, val; snd_soc_unregister_codec(&spi->dev);
struct ak4104_private *ak4104 = spi_get_drvdata(spi); kfree(spi_get_drvdata(spi));
val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1);
if (val < 0)
return val;
/* clear power-up and non-reset bits */
val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val);
if (ret < 0)
return ret;
ak4104_codec = NULL;
kfree(ak4104);
return 0; return 0;
} }
static int ak4104_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = ak4104_codec;
int ret;
/* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
socdev->card->codec = codec;
/* Register PCMs */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
dev_err(codec->dev, "failed to create pcms\n");
return ret;
}
return 0;
}
static int ak4104_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
snd_soc_free_pcms(socdev);
return 0;
};
struct snd_soc_codec_device soc_codec_device_ak4104 = {
.probe = ak4104_probe,
.remove = ak4104_remove
};
EXPORT_SYMBOL_GPL(soc_codec_device_ak4104);
static struct spi_driver ak4104_spi_driver = { static struct spi_driver ak4104_spi_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,

View File

@ -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

View File

@ -31,11 +31,11 @@
#define AK4535_VERSION "0.3" #define AK4535_VERSION "0.3"
struct snd_soc_codec_device soc_codec_dev_ak4535;
/* codec private data */ /* codec private data */
struct ak4535_priv { struct ak4535_priv {
unsigned int sysclk; 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_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
int rate = params_rate(params), fs = 256; 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, static int ak4535_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 i; u16 i, mute_reg;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: 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; break;
case SND_SOC_BIAS_PREPARE: 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; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
i = ak4535_read_reg_cache(codec, AK4535_PM1); 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, .set_sysclk = ak4535_set_dai_sysclk,
}; };
struct snd_soc_dai ak4535_dai = { static struct snd_soc_dai_driver ak4535_dai = {
.name = "AK4535", .name = "ak4535-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &ak4535_dai_ops, .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); ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0; 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_sync(codec);
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
} }
/* static int ak4535_probe(struct snd_soc_codec *codec)
* initialise the AK4535 driver
* register the mixer and dsp interfaces with the kernel
*/
static int ak4535_init(struct snd_soc_device *socdev)
{ {
struct snd_soc_codec *codec = socdev->card->codec; struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
codec->name = "AK4535"; printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
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) codec->control_data = ak4535->control_data;
return -ENOMEM;
/* 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;
}
/* power on device */ /* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 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)); ARRAY_SIZE(ak4535_snd_controls));
ak4535_add_widgets(codec); ak4535_add_widgets(codec);
return ret; return 0;
pcm_err:
kfree(codec->reg_cache);
return ret;
} }
static struct snd_soc_device *ak4535_socdev; /* 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_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) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
static int ak4535_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
const struct i2c_device_id *id)
{ {
struct snd_soc_device *socdev = ak4535_socdev; struct ak4535_priv *ak4535;
struct snd_soc_codec *codec = socdev->card->codec;
int ret; int ret;
i2c_set_clientdata(i2c, codec); ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
codec->control_data = i2c; if (ak4535 == NULL)
return -ENOMEM;
ret = ak4535_init(socdev); 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) if (ret < 0)
printk(KERN_ERR "failed to initialise AK4535\n"); kfree(ak4535);
return ret; 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); snd_soc_unregister_codec(&client->dev);
kfree(codec->reg_cache); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = { static struct i2c_driver ak4535_i2c_driver = {
.driver = { .driver = {
.name = "AK4535 I2C Codec", .name = "ak4535-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = ak4535_i2c_probe, .probe = ak4535_i2c_probe,
.remove = ak4535_i2c_remove, .remove = __devexit_p(ak4535_i2c_remove),
.id_table = ak4535_i2c_id, .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 #endif
static int ak4535_probe(struct platform_device *pdev)
{
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;
#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
if (ret != 0) {
kfree(snd_soc_codec_get_drvdata(codec));
kfree(codec);
}
return ret;
}
/* power down chip */
static int ak4535_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)
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) static int __init ak4535_modinit(void)
{ {
return snd_soc_register_dai(&ak4535_dai); int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&ak4535_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
ret);
}
#endif
return ret;
} }
module_init(ak4535_modinit); module_init(ak4535_modinit);
static void __exit ak4535_exit(void) static void __exit ak4535_exit(void)
{ {
snd_soc_unregister_dai(&ak4535_dai); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&ak4535_i2c_driver);
#endif
} }
module_exit(ak4535_exit); module_exit(ak4535_exit);

View File

@ -36,12 +36,4 @@
#define AK4535_CACHEREGNUM 0x10 #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 #endif

View File

@ -30,8 +30,6 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include "ak4642.h"
#define AK4642_VERSION "0.0.1" #define AK4642_VERSION "0.0.1"
#define PW_MGMT1 0x00 #define PW_MGMT1 0x00
@ -102,7 +100,6 @@
#define FS3 (1 << 5) #define FS3 (1 << 5)
#define FS_MASK (FS0 | FS1 | FS2 | FS3) #define FS_MASK (FS0 | FS1 | FS2 | FS3)
struct snd_soc_codec_device soc_codec_dev_ak4642;
/* /*
* Playback Volume (table 39) * Playback Volume (table 39)
@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
/* codec private data */ /* codec private data */
struct ak4642_priv { 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 * ak4642 register cache
*/ */
@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
.hw_params = ak4642_dai_hw_params, .hw_params = ak4642_dai_hw_params,
}; };
struct snd_soc_dai ak4642_dai = { static struct snd_soc_dai_driver ak4642_dai = {
.name = "AK4642", .name = "ak4642-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = {
.ops = &ak4642_dai_ops, .ops = &ak4642_dai_ops,
.symmetric_rates = 1, .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); ak4642_sync(codec);
return 0; return 0;
} }
/*
* initialise the AK4642 driver static int ak4642_probe(struct snd_soc_codec *codec)
* register the mixer and dsp interfaces with the kernel
*/
static int ak4642_init(struct ak4642_priv *ak4642)
{ {
struct snd_soc_codec *codec = &ak4642->codec; struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
if (ak4642_codec) { dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
dev_err(codec->dev, "Another ak4642 is registered\n");
return -EINVAL;
}
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->hw_write = (hw_write_t)i2c_master_send;
codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); codec->control_data = ak4642->control_data;
codec->reg_cache = kmemdup(ak4642_reg,
sizeof(ak4642_reg), GFP_KERNEL);
if (!codec->reg_cache)
return -ENOMEM;
ak4642_dai.dev = codec->dev; return 0;
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;
}
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;
} }
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) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int ak4642_i2c_probe(struct i2c_client *i2c, static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct ak4642_priv *ak4642; struct ak4642_priv *ak4642;
struct snd_soc_codec *codec;
int ret; int ret;
ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
if (!ak4642) if (ak4642 == NULL)
return -ENOMEM; return -ENOMEM;
codec = &ak4642->codec;
codec->dev = &i2c->dev;
i2c_set_clientdata(i2c, ak4642); i2c_set_clientdata(i2c, ak4642);
codec->control_data = i2c; ak4642->control_data = i2c;
ak4642->control_type = SND_SOC_I2C;
ret = ak4642_init(ak4642); ret = snd_soc_register_codec(&i2c->dev,
if (ret < 0) { &soc_codec_dev_ak4642, &ak4642_dai, 1);
printk(KERN_ERR "failed to initialise AK4642\n"); if (ret < 0)
kfree(ak4642); kfree(ak4642);
}
return ret; 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_codec(&client->dev);
kfree(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;
return 0; return 0;
} }
@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
static struct i2c_driver ak4642_i2c_driver = { static struct i2c_driver ak4642_i2c_driver = {
.driver = { .driver = {
.name = "AK4642 I2C Codec", .name = "ak4642-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = ak4642_i2c_probe, .probe = ak4642_i2c_probe,
.remove = ak4642_i2c_remove, .remove = __devexit_p(ak4642_i2c_remove),
.id_table = ak4642_i2c_id, .id_table = ak4642_i2c_id,
}; };
#endif #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) static int __init ak4642_modinit(void)
{ {
int ret = 0; int ret = 0;

View File

@ -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

View File

@ -23,11 +23,11 @@
#include "ak4671.h" #include "ak4671.h"
static struct snd_soc_codec *ak4671_codec;
/* codec private data */ /* codec private data */
struct ak4671_priv { struct ak4671_priv {
struct snd_soc_codec codec; enum snd_soc_control_type control_type;
void *control_data;
u8 reg_cache[AK4671_CACHEREGNUM]; u8 reg_cache[AK4671_CACHEREGNUM];
}; };
@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
.set_fmt = ak4671_set_dai_fmt, .set_fmt = ak4671_set_dai_fmt,
}; };
struct snd_soc_dai ak4671_dai = { static struct snd_soc_dai_driver ak4671_dai = {
.name = "AK4671", .name = "ak4671-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = {
.formats = AK4671_FORMATS,}, .formats = AK4671_FORMATS,},
.ops = &ak4671_dai_ops, .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 ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_codec *codec; int ret;
int ret = 0;
if (ak4671_codec == NULL) { codec->hw_write = (hw_write_t)i2c_master_send;
dev_err(&pdev->dev, "Codec device not registered\n"); codec->bias_level = SND_SOC_BIAS_OFF;
return -ENODEV;
}
socdev->card->codec = ak4671_codec; ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
codec = ak4671_codec;
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "failed to create pcms: %d\n", ret); dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto pcm_err; return ret;
} }
snd_soc_add_controls(codec, ak4671_snd_controls, 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); ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return ret; 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); ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0; return 0;
} }
struct snd_soc_codec_device soc_codec_dev_ak4671 = { static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.probe = ak4671_probe, .probe = ak4671_probe,
.remove = ak4671_remove, .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, static int __devinit ak4671_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct ak4671_priv *ak4671; struct ak4671_priv *ak4671;
struct snd_soc_codec *codec; int ret;
ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
if (ak4671 == NULL) if (ak4671 == NULL)
return -ENOMEM; return -ENOMEM;
codec = &ak4671->codec;
codec->hw_write = (hw_write_t)i2c_master_send;
i2c_set_clientdata(client, ak4671); i2c_set_clientdata(client, ak4671);
codec->control_data = client; ak4671->control_data = client;
ak4671->control_type = SND_SOC_I2C;
codec->dev = &client->dev; ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_ak4671, &ak4671_dai, 1);
return ak4671_register(ak4671, SND_SOC_I2C); if (ret < 0)
kfree(ak4671);
return ret;
} }
static __devexit int ak4671_i2c_remove(struct i2c_client *client) static __devexit int ak4671_i2c_remove(struct i2c_client *client)
{ {
struct ak4671_priv *ak4671 = i2c_get_clientdata(client); snd_soc_unregister_codec(&client->dev);
kfree(i2c_get_clientdata(client));
ak4671_unregister(ak4671);
return 0; return 0;
} }
@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
static struct i2c_driver ak4671_i2c_driver = { static struct i2c_driver ak4671_i2c_driver = {
.driver = { .driver = {
.name = "ak4671", .name = "ak4671-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = ak4671_i2c_probe, .probe = ak4671_i2c_probe,

View File

@ -150,7 +150,4 @@
/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
#define AK4671_MUTEN 0x04 #define AK4671_MUTEN 0x04
extern struct snd_soc_dai ak4671_dai;
extern struct snd_soc_codec_device soc_codec_dev_ak4671;
#endif #endif

View File

@ -30,6 +30,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/mfd/davinci_voicecodec.h> #include <linux/mfd/davinci_voicecodec.h>
#include <linux/spi/spi.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
@ -41,8 +42,6 @@
#include <mach/dm365.h> #include <mach/dm365.h>
#include "cq93vc.h"
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
unsigned int reg) unsigned int reg)
{ {
@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {
.set_sysclk = cq93vc_set_dai_sysclk, .set_sysclk = cq93vc_set_dai_sysclk,
}; };
struct snd_soc_dai cq93vc_dai = { static struct snd_soc_dai_driver cq93vc_dai = {
.name = "CQ93VC", .name = "cq93vc-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {
.formats = CQ93VC_FORMATS,}, .formats = CQ93VC_FORMATS,},
.ops = &cq93vc_dai_ops, .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); cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
} }
static struct snd_soc_codec *cq93vc_codec; static int cq93vc_probe(struct snd_soc_codec *codec)
static int cq93vc_probe(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct davinci_vc *davinci_vc = codec->dev->platform_data;
struct device *dev = &pdev->dev;
struct snd_soc_codec *codec;
int ret;
socdev->card->codec = cq93vc_codec; davinci_vc->cq93vc.codec = codec;
codec = socdev->card->codec; codec->control_data = davinci_vc;
/* 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;
}
/* Set controls */ /* Set controls */
snd_soc_add_controls(codec, cq93vc_snd_controls, snd_soc_add_controls(codec, cq93vc_snd_controls,
@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)
return 0; 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); cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0; 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, .probe = cq93vc_probe,
.remove = cq93vc_remove, .remove = cq93vc_remove,
.resume = cq93vc_resume, .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); return snd_soc_register_codec(&pdev->dev,
struct snd_soc_codec *codec; &soc_codec_dev_cq93vc, &cq93vc_dai, 1);
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;
} }
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); snd_soc_unregister_codec(&pdev->dev);
struct snd_soc_codec *codec = socdev->card->codec;
snd_soc_unregister_dai(&cq93vc_dai);
snd_soc_unregister_codec(&codec);
kfree(codec);
cq93vc_codec = NULL;
return 0; return 0;
} }
static struct platform_driver cq93vc_codec_driver = { static struct platform_driver cq93vc_codec_driver = {
.driver = { .driver = {
.name = "cq93vc", .name = "cq93vc-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = cq93vc_codec_probe,
.remove = __devexit_p(cq93vc_codec_remove), .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); module_init(cq93vc_init);
static __exit void cq93vc_exit(void) static void __exit cq93vc_exit(void)
{ {
platform_driver_unregister(&cq93vc_codec_driver); platform_driver_unregister(&cq93vc_codec_driver);
} }

View File

@ -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

View File

@ -31,8 +31,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include "cs4270.h"
/* /*
* The codec isn't really big-endian or little-endian, since the I2S * The codec isn't really big-endian or little-endian, since the I2S
* interface requires data to be sent serially with the MSbit first. * 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 */ /* Private data for the CS4270 */
struct cs4270_private { struct cs4270_private {
struct snd_soc_codec codec; enum snd_soc_control_type control_type;
void *control_data;
u8 reg_cache[CS4270_NUMREGS]; u8 reg_cache[CS4270_NUMREGS];
unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mclk; /* Input frequency of the MCLK pin */
unsigned int mode; /* The mode (I2S or left-justified) */ 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 snd_soc_codec *codec = codec_dai->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(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; 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; return 0;
} }
@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret; int ret;
unsigned int i; unsigned int i;
@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
snd_soc_get_volsw, cs4270_soc_put_mute), 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 = { static struct snd_soc_dai_ops cs4270_dai_ops = {
.hw_params = cs4270_hw_params, .hw_params = cs4270_hw_params,
.set_sysclk = cs4270_set_dai_sysclk, .set_sysclk = cs4270_set_dai_sysclk,
@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
.digital_mute = cs4270_dai_mute, .digital_mute = cs4270_dai_mute,
}; };
struct snd_soc_dai cs4270_dai = { struct snd_soc_dai_driver cs4270_dai = {
.name = "cs4270", .name = "cs4270-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = 0, .rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 4000,
.rate_max = 216000,
.formats = CS4270_FORMATS, .formats = CS4270_FORMATS,
}, },
.capture = { .capture = {
.stream_name = "Capture", .stream_name = "Capture",
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = 0, .rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 4000,
.rate_max = 216000,
.formats = CS4270_FORMATS, .formats = CS4270_FORMATS,
}, },
.ops = &cs4270_dai_ops, .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 * This function is called when ASoC has all the pieces it needs to
* instantiate a sound driver. * instantiate a sound driver.
*/ */
static int cs4270_probe(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); struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int i, ret; int i, ret, reg;
/* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ codec->control_data = cs4270->control_data;
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)
{
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);
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;
/* The I2C interface is set up, so pre-fill our register cache */ /* The I2C interface is set up, so pre-fill our register cache */
ret = cs4270_fill_cache(codec); ret = cs4270_fill_cache(codec);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "failed to fill register cache\n"); dev_err(codec->dev, "failed to fill register cache\n");
goto error_free_codec; return ret;
} }
/* Disable auto-mute. This feature appears to be buggy. In some /* 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; reg &= ~CS4270_MUTE_AUTO;
ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "i2c write failed\n"); dev_err(codec->dev, "i2c write failed\n");
return ret; return ret;
} }
@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "i2c write failed\n"); dev_err(codec->dev, "i2c write failed\n");
return ret; return ret;
} }
/* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI /* Add the non-DAPM controls */
* structure for each CS4270 device, but the machine driver needs to ret = snd_soc_add_controls(codec, cs4270_snd_controls,
* have a pointer to the DAI structure, so for now it must be a global ARRAY_SIZE(cs4270_snd_controls));
* 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);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "failed to register DAIe\n"); dev_err(codec->dev, "failed to add controls\n");
goto error_free_codec; 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; return 0;
error_free_codec: error_free_regulators:
kfree(cs4270); regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
cs4270_codec = NULL; cs4270->supplies);
cs4270_dai.dev = NULL;
return ret; return ret;
} }
/** /**
* cs4270_i2c_remove - remove an I2C device * cs4270_remove - ASoC remove function
* @i2c_client: the I2C client object * @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); regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
cs4270_codec = NULL; regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
cs4270_dai.dev = NULL;
return 0; 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 #ifdef CONFIG_PM
@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
* and all registers are written back to the hardware when resuming. * 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); struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int reg, ret; int reg, ret;
@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
return 0; 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 cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c_client = codec->control_data; struct i2c_client *i2c_client = codec->control_data;
int reg; int reg;
@ -895,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
#define cs4270_soc_resume NULL #define cs4270_soc_resume NULL
#endif /* CONFIG_PM */ #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 * cs4270_i2c_driver - I2C device identification
* *
@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
*/ */
static struct i2c_driver cs4270_i2c_driver = { static struct i2c_driver cs4270_i2c_driver = {
.driver = { .driver = {
.name = "cs4270", .name = "cs4270-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.id_table = cs4270_id, .id_table = cs4270_id,
@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = {
.remove = cs4270_i2c_remove, .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) static int __init cs4270_init(void)
{ {
pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");

View File

@ -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

View File

@ -42,15 +42,14 @@ enum master_slave_mode {
}; };
struct cs42l51_private { struct cs42l51_private {
enum snd_soc_control_type control_type;
void *control_data;
unsigned int mclk; unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */ unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func; enum master_slave_mode func;
struct snd_soc_codec codec;
u8 reg_cache[CS42L51_NUMREGS]; u8 reg_cache[CS42L51_NUMREGS];
}; };
static struct snd_soc_codec *cs42l51_codec;
#define CS42L51_FORMATS ( \ #define CS42L51_FORMATS ( \
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ 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; 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, static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) 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 snd_soc_codec *codec = codec_dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(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; 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; return 0;
} }
@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret; int ret;
unsigned int i; unsigned int i;
@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {
.digital_mute = cs42l51_dai_mute, .digital_mute = cs42l51_dai_mute,
}; };
struct snd_soc_dai cs42l51_dai = { static struct snd_soc_dai_driver cs42l51_dai = {
.name = "CS42L51 HiFi", .name = "cs42l51-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {
}, },
.ops = &cs42l51_dai_ops, .ops = &cs42l51_dai_ops,
}; };
EXPORT_SYMBOL_GPL(cs42l51_dai);
static int cs42l51_probe(struct snd_soc_codec *codec)
static int cs42l51_probe(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_codec *codec; int ret, reg;
int ret = 0;
if (!cs42l51_codec) { codec->control_data = cs42l51->control_data;
dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
return -EINVAL;
}
socdev->card->codec = cs42l51_codec; ret = cs42l51_fill_cache(codec);
codec = socdev->card->codec;
/* Register PCMs */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to create PCMs\n"); dev_err(codec->dev, "failed to fill register cache\n");
return ret; return ret;
} }
ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
if (ret < 0) {
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, snd_soc_add_controls(codec, cs42l51_snd_controls,
ARRAY_SIZE(cs42l51_snd_controls)); ARRAY_SIZE(cs42l51_snd_controls));
snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)
return 0; 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); /* Verify that we have a CS42L51 */
snd_soc_dapm_free(socdev); 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; return 0;
} }
struct snd_soc_codec_device soc_codec_device_cs42l51 = { static const struct i2c_device_id cs42l51_id[] = {
.probe = cs42l51_probe, {"cs42l51", 0},
.remove = cs42l51_remove {}
};
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) static int __init cs42l51_init(void)
{ {

View File

@ -158,6 +158,4 @@
#define CS42L51_LASTREG 0x20 #define CS42L51_LASTREG 0x20
#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) #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 #endif

View File

@ -24,7 +24,8 @@
struct cx20442_priv { struct cx20442_priv {
struct snd_soc_codec codec; enum snd_soc_control_type control_type;
void *control_data;
u8 reg_cache[1]; 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; u8 *reg_cache = codec->reg_cache;
if (reg >= codec->reg_cache_size) if (reg >= codec->driver->reg_cache_size)
return -EINVAL; return -EINVAL;
return reg_cache[reg]; 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, static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value) unsigned int value)
{ {
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
u8 *reg_cache = codec->reg_cache; u8 *reg_cache = codec->reg_cache;
int vls, vsp, old, len; int vls, vsp, old, len;
char buf[18]; char buf[18];
if (reg >= codec->reg_cache_size) if (reg >= codec->driver->reg_cache_size)
return -EINVAL; return -EINVAL;
/* hw_write and control_data pointers required for talking to the modem /* hw_write and control_data pointers required for talking to the modem
* are expected to be set by the line discipline initialization code */ * 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; return -EIO;
old = reg_cache[reg]; old = reg_cache[reg];
@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
return -ENOMEM; return -ENOMEM;
dev_dbg(codec->dev, "%s: %s\n", __func__, buf); 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 -EIO;
return 0; return 0;
} }
/* Moved up here as line discipline referres it during initialization */
static struct snd_soc_codec *cx20442_codec;
/* /*
* Line discpline related code * Line discpline related code
* *
@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";
/* Line discipline .open() */ /* Line discipline .open() */
static int v253_open(struct tty_struct *tty) static int v253_open(struct tty_struct *tty)
{ {
struct snd_soc_codec *codec = cx20442_codec;
int ret, len = strlen(v253_init); int ret, len = strlen(v253_init);
/* Doesn't make sense without write callback */ /* Doesn't make sense without write callback */
if (!tty->ops->write) if (!tty->ops->write)
return -EINVAL; return -EINVAL;
/* Pass the codec structure address for use by other ldisc callbacks */ /* Won't work if no codec pointer has been passed by a card driver */
tty->disc_data = codec; if (!tty->disc_data)
return -ENODEV;
if (tty->ops->write(tty, v253_init, len) != len) { if (tty->ops->write(tty, v253_init, len) != len) {
ret = -EIO; ret = -EIO;
@ -253,15 +251,18 @@ err:
static void v253_close(struct tty_struct *tty) static void v253_close(struct tty_struct *tty)
{ {
struct snd_soc_codec *codec = tty->disc_data; struct snd_soc_codec *codec = tty->disc_data;
struct cx20442_priv *cx20442;
tty->disc_data = NULL; tty->disc_data = NULL;
if (!codec) if (!codec)
return; return;
cx20442 = snd_soc_codec_get_drvdata(codec);
/* Prevent the codec driver from further accessing the modem */ /* Prevent the codec driver from further accessing the modem */
codec->hw_write = NULL; codec->hw_write = NULL;
codec->control_data = NULL; cx20442->control_data = NULL;
codec->pop_time = 0; codec->pop_time = 0;
} }
@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count) const unsigned char *cp, char *fp, int count)
{ {
struct snd_soc_codec *codec = tty->disc_data; struct snd_soc_codec *codec = tty->disc_data;
struct cx20442_priv *cx20442;
if (!codec) if (!codec)
return; return;
if (!codec->control_data) { cx20442 = snd_soc_codec_get_drvdata(codec);
if (!cx20442->control_data) {
/* First modem response, complete setup procedure */ /* First modem response, complete setup procedure */
/* Set up codec driver access to modem controls */ /* 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->hw_write = (hw_write_t)tty->ops->write;
codec->pop_time = 1; codec->pop_time = 1;
} }
@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);
* Codec DAI * Codec DAI
*/ */
struct snd_soc_dai cx20442_dai = { static struct snd_soc_dai_driver cx20442_dai = {
.name = "CX20442", .name = "cx20442-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE, .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;
/* 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_add_widgets(codec);
pcm_err:
return ret;
}
/* power down chip */
static int cx20442_codec_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 cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
};
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 cx20442_priv *cx20442;
struct snd_soc_codec *codec;
cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
if (cx20442 == NULL) if (cx20442 == NULL)
return -ENOMEM; return -ENOMEM;
snd_soc_codec_set_drvdata(codec, cx20442);
codec = &cx20442->codec; cx20442_add_widgets(codec);
codec->control_data = NULL; cx20442->control_data = NULL;
codec->hw_write = NULL; codec->hw_write = NULL;
codec->pop_time = 0; codec->pop_time = 0;
codec->dev = &pdev->dev; return 0;
platform_set_drvdata(pdev, cx20442); }
return cx20442_register(cx20442); /* power down chip */
static int cx20442_codec_remove(struct snd_soc_codec *codec)
{
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
if (cx20442->control_data) {
struct tty_struct *tty = cx20442->control_data;
tty_hangup(tty);
}
kfree(cx20442);
return 0;
}
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,
};
static int cx20442_platform_probe(struct platform_device *pdev)
{
return snd_soc_register_codec(&pdev->dev,
&cx20442_codec_dev, &cx20442_dai, 1);
} }
static int __exit cx20442_platform_remove(struct platform_device *pdev) static int __exit cx20442_platform_remove(struct platform_device *pdev)
{ {
struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); snd_soc_unregister_codec(&pdev->dev);
cx20442_unregister(cx20442);
return 0; return 0;
} }
static struct platform_driver cx20442_platform_driver = { static struct platform_driver cx20442_platform_driver = {
.driver = { .driver = {
.name = "cx20442", .name = "cx20442-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = cx20442_platform_probe, .probe = cx20442_platform_probe,
@ -487,4 +412,4 @@ module_exit(cx20442_exit);
MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
MODULE_AUTHOR("Janusz Krzysztofik"); MODULE_AUTHOR("Janusz Krzysztofik");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:cx20442"); MODULE_ALIAS("platform:cx20442-codec");

View File

@ -13,8 +13,6 @@
#ifndef _CX20442_CODEC_H #ifndef _CX20442_CODEC_H
#define _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; extern struct tty_ldisc_ops v253_ops;
#endif #endif

View File

@ -25,8 +25,6 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include "da7210.h"
/* DA7210 register space */ /* DA7210 register space */
#define DA7210_STATUS 0x02 #define DA7210_STATUS 0x02
#define DA7210_STARTUP1 0x03 #define DA7210_STARTUP1 0x03
@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
/* Codec private data */ /* Codec private data */
struct da7210_priv { 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 * 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 *cache = codec->reg_cache;
u8 data[2]; u8 data[2];
BUG_ON(codec->volatile_register); BUG_ON(codec->driver->volatile_register);
data[0] = reg & 0xff; data[0] = reg & 0xff;
data[1] = value & 0xff; data[1] = value & 0xff;
if (reg >= codec->reg_cache_size) if (reg >= codec->driver->reg_cache_size)
return -EIO; return -EIO;
if (2 != codec->hw_write(codec->control_data, data, 2)) 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_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
u32 dai_cfg1; u32 dai_cfg1;
u32 hpf_reg, hpf_mask, hpf_value; u32 hpf_reg, hpf_mask, hpf_value;
u32 fs, bypass; u32 fs, bypass;
@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {
.set_fmt = da7210_set_dai_fmt, .set_fmt = da7210_set_dai_fmt,
}; };
struct snd_soc_dai da7210_dai = { static struct snd_soc_dai_driver da7210_dai = {
.name = "DA7210 IIS", .name = "da7210-hifi",
.id = 0,
/* playback capabilities */ /* playback capabilities */
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {
.ops = &da7210_dai_ops, .ops = &da7210_dai_ops,
.symmetric_rates = 1, .symmetric_rates = 1,
}; };
EXPORT_SYMBOL_GPL(da7210_dai);
/* static int da7210_probe(struct snd_soc_codec *codec)
* Initialize the DA7210 driver
* register the mixer and dsp interfaces with the kernel
*/
static int da7210_init(struct da7210_priv *da7210)
{ {
struct snd_soc_codec *codec = &da7210->codec; struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
if (da7210_codec) { dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
dev_err(codec->dev, "Another da7210 is registered\n");
return -EINVAL;
}
mutex_init(&codec->mutex); codec->control_data = da7210->control_data;
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->hw_write = (hw_write_t)i2c_master_send; 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 /* FIXME
* *
@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)
/* Activate all enabled subsystem */ /* Activate all enabled subsystem */
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
return ret; snd_soc_add_controls(codec, da7210_snd_controls,
ARRAY_SIZE(da7210_snd_controls));
codec_err: dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
snd_soc_unregister_codec(codec);
init_err:
kfree(codec->reg_cache);
codec->reg_cache = NULL;
return ret;
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) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int __devinit da7210_i2c_probe(struct i2c_client *i2c, static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct da7210_priv *da7210; struct da7210_priv *da7210;
struct snd_soc_codec *codec;
int ret; int ret;
da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
if (!da7210) if (!da7210)
return -ENOMEM; return -ENOMEM;
codec = &da7210->codec;
codec->dev = &i2c->dev;
i2c_set_clientdata(i2c, da7210); i2c_set_clientdata(i2c, da7210);
codec->control_data = i2c; da7210->control_data = i2c;
da7210->control_type = SND_SOC_I2C;
ret = da7210_init(da7210); ret = snd_soc_register_codec(&i2c->dev,
if (ret < 0) { &soc_codec_dev_da7210, &da7210_dai, 1);
pr_err("Failed to initialise da7210 audio codec\n"); if (ret < 0)
kfree(da7210); kfree(da7210);
}
return ret; return ret;
} }
static int __devexit da7210_i2c_remove(struct i2c_client *client) static int __devexit da7210_i2c_remove(struct i2c_client *client)
{ {
struct da7210_priv *da7210 = i2c_get_clientdata(client); snd_soc_unregister_codec(&client->dev);
kfree(i2c_get_clientdata(client));
snd_soc_unregister_dai(&da7210_dai);
kfree(da7210->codec.reg_cache);
kfree(da7210);
da7210_codec = NULL;
return 0; return 0;
} }
@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
/* I2C codec control layer */ /* I2C codec control layer */
static struct i2c_driver da7210_i2c_driver = { static struct i2c_driver da7210_i2c_driver = {
.driver = { .driver = {
.name = "DA7210 I2C Codec", .name = "da7210-codec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = da7210_i2c_probe, .probe = da7210_i2c_probe,
@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = {
}; };
#endif #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) static int __init da7210_modinit(void)
{ {
int ret = 0; int ret = 0;

View File

@ -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

View File

@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {
struct jz4740_codec { struct jz4740_codec {
void __iomem *base; void __iomem *base;
struct resource *mem; 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, static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
unsigned int reg) 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)); return readl(jz4740_codec->base + (reg << 2));
} }
static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val) 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)); writel(val, jz4740_codec->base + (reg << 2));
return 0; return 0;
@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
{ {
uint32_t val; uint32_t val;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec =rtd->codec;
struct snd_soc_codec *codec = socdev->card->codec;
switch (params_rate(params)) { switch (params_rate(params)) {
case 8000: case 8000:
@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
.hw_params = jz4740_codec_hw_params, .hw_params = jz4740_codec_hw_params,
}; };
struct snd_soc_dai jz4740_codec_dai = { static struct snd_soc_dai_driver jz4740_codec_dai = {
.name = "jz4740", .name = "jz4740-hifi",
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 2, .channels_min = 2,
@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {
.ops = &jz4740_codec_dai_ops, .ops = &jz4740_codec_dai_ops,
.symmetric_rates = 1, .symmetric_rates = 1,
}; };
EXPORT_SYMBOL_GPL(jz4740_codec_dai);
static void jz4740_codec_wakeup(struct snd_soc_codec *codec) 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; return 0;
} }
static struct snd_soc_codec *jz4740_codec_codec; static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
static int jz4740_codec_dev_probe(struct platform_device *pdev)
{ {
int ret; snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
struct snd_soc_device *socdev = platform_get_drvdata(pdev); JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
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_add_controls(codec, jz4740_codec_controls, snd_soc_add_controls(codec, jz4740_codec_controls,
ARRAY_SIZE(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); snd_soc_dapm_new_widgets(codec);
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; 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); jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP #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); 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); 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 #define jz4740_codec_resume NULL
#endif #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, .probe = jz4740_codec_dev_probe,
.remove = jz4740_codec_dev_remove, .remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend, .suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume, .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) static int __devinit jz4740_codec_probe(struct platform_device *pdev)
{ {
int ret; int ret;
struct jz4740_codec *jz4740_codec; struct jz4740_codec *jz4740_codec;
struct snd_soc_codec *codec;
struct resource *mem; struct resource *mem;
jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); 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->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); 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) { if (ret) {
dev_err(&pdev->dev, "Failed to register codec\n"); dev_err(&pdev->dev, "Failed to register codec\n");
goto err_iounmap; 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; return 0;
err_unregister_codec:
snd_soc_unregister_codec(codec);
err_iounmap: err_iounmap:
iounmap(jz4740_codec->base); iounmap(jz4740_codec->base);
err_release_mem_region: 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 jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
struct resource *mem = jz4740_codec->mem; struct resource *mem = jz4740_codec->mem;
snd_soc_unregister_dai(&jz4740_codec_dai); snd_soc_unregister_codec(&pdev->dev);
snd_soc_unregister_codec(&jz4740_codec->codec);
iounmap(jz4740_codec->base); iounmap(jz4740_codec->base);
release_mem_region(mem->start, resource_size(mem)); release_mem_region(mem->start, resource_size(mem));

View File

@ -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

View File

@ -32,8 +32,8 @@
#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000) SNDRV_PCM_RATE_48000)
struct snd_soc_dai pcm3008_dai = { static struct snd_soc_dai_driver pcm3008_dai = {
.name = "PCM3008 HiFi", .name = "pcm3008-hifi",
.playback = { .playback = {
.stream_name = "PCM3008 Playback", .stream_name = "PCM3008 Playback",
.channels_min = 1, .channels_min = 1,
@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE,
}, },
}; };
EXPORT_SYMBOL_GPL(pcm3008_dai);
static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) 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); 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 pcm3008_setup_data *setup = codec->dev->platform_data;
struct snd_soc_codec *codec;
struct pcm3008_setup_data *setup = socdev->codec_data;
int ret = 0; int ret = 0;
printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); 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 /* DEM1 DEM0 DE-EMPHASIS_MODE
* Low Low De-emphasis 44.1 kHz ON * Low Low De-emphasis 44.1 kHz ON
* Low High De-emphasis OFF * Low High De-emphasis OFF
@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
gpio_err: gpio_err:
pcm3008_gpio_free(setup); pcm3008_gpio_free(setup);
pcm_err:
kfree(socdev->card->codec);
return ret; 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 pcm3008_setup_data *setup = codec->dev->platform_data;
struct snd_soc_codec *codec = socdev->card->codec;
struct pcm3008_setup_data *setup = socdev->codec_data;
if (!codec)
return 0;
pcm3008_gpio_free(setup); pcm3008_gpio_free(setup);
snd_soc_free_pcms(socdev);
kfree(socdev->card->codec);
return 0; return 0;
} }
#ifdef CONFIG_PM #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 = codec->dev->platform_data;
struct pcm3008_setup_data *setup = socdev->codec_data;
gpio_set_value(setup->pdad_pin, 0); gpio_set_value(setup->pdad_pin, 0);
gpio_set_value(setup->pdda_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; 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 = codec->dev->platform_data;
struct pcm3008_setup_data *setup = socdev->codec_data;
gpio_set_value(setup->pdad_pin, 1); gpio_set_value(setup->pdad_pin, 1);
gpio_set_value(setup->pdda_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 #define pcm3008_soc_resume NULL
#endif #endif
struct snd_soc_codec_device soc_codec_dev_pcm3008 = { static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
.probe = pcm3008_soc_probe, .probe = pcm3008_soc_probe,
.remove = pcm3008_soc_remove, .remove = pcm3008_soc_remove,
.suspend = pcm3008_soc_suspend, .suspend = pcm3008_soc_suspend,
.resume = pcm3008_soc_resume, .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_dai(&pcm3008_dai); return snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_pcm3008, &pcm3008_dai, 1);
} }
module_init(pcm3008_init);
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 platform_driver_register(&pcm3008_codec_driver);
}
module_init(pcm3008_modinit);
static void __exit pcm3008_exit(void) static void __exit pcm3008_exit(void)
{ {
snd_soc_unregister_dai(&pcm3008_dai); platform_driver_unregister(&pcm3008_codec_driver);
} }
module_exit(pcm3008_exit); module_exit(pcm3008_exit);

View File

@ -19,7 +19,4 @@ struct pcm3008_setup_data {
unsigned pdda_pin; unsigned pdda_pin;
}; };
extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
extern struct snd_soc_dai pcm3008_dai;
#endif #endif

Some files were not shown because too many files have changed in this diff Show More