ASoC: multi-component - ASoC Multi-Component Support
This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi <timur@freescale.com> Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Seungwhan Youn <sw.youn@samsung.com> MPC8610 and PPC fixes. Signed-off-by: Timur Tabi <timur@freescale.com> i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> CC: Tony Lindgren <tony@atomide.com> CC: Nicolas Ferre <nicolas.ferre@atmel.com> CC: Kevin Hilman <khilman@deeprootsystems.com> CC: Sascha Hauer <s.hauer@pengutronix.de> CC: Atsushi Nemoto <anemo@mba.ocn.ne.jp> CC: Kuninori Morimoto <morimoto.kuninori@renesas.com> CC: Daniel Gloeckner <dg@emlix.com> CC: Manuel Lauss <mano@roarinelk.homelinux.net> CC: Mike Frysinger <vapier.adi@gmail.com> CC: Arnaud Patard <apatard@mandriva.com> CC: Wan ZongShun <mcuos.com@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
This commit is contained in:
parent
bda7d2a862
commit
f0fba2ad1b
|
@ -295,6 +295,18 @@ static void davinci_init_wdt(void)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct platform_device davinci_pcm_device = {
|
||||
.name = "davinci-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static void davinci_init_pcm(void)
|
||||
{
|
||||
platform_device_register(&davinci_pcm_device);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct davinci_timer_instance davinci_timer_instance[2] = {
|
||||
{
|
||||
.base = DAVINCI_TIMER0_BASE,
|
||||
|
@ -315,6 +327,7 @@ static int __init davinci_init_devices(void)
|
|||
/* please keep these calls, and their implementations above,
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
davinci_init_pcm();
|
||||
davinci_init_wdt();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -732,9 +732,15 @@ static struct platform_device ep93xx_i2s_device = {
|
|||
.resource = ep93xx_i2s_resource,
|
||||
};
|
||||
|
||||
static struct platform_device ep93xx_pcm_device = {
|
||||
.name = "ep93xx-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init ep93xx_register_i2s(void)
|
||||
{
|
||||
platform_device_register(&ep93xx_i2s_device);
|
||||
platform_device_register(&ep93xx_pcm_device);
|
||||
}
|
||||
|
||||
#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
|
||||
|
|
|
@ -896,10 +896,16 @@ static struct platform_device kirkwood_i2s_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct platform_device kirkwood_pcm_device = {
|
||||
.name = "kirkwood-pcm",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init kirkwood_audio_init(void)
|
||||
{
|
||||
kirkwood_clk_ctrl |= CGC_AUDIO;
|
||||
platform_device_register(&kirkwood_i2s_device);
|
||||
platform_device_register(&kirkwood_pcm_device);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -653,8 +653,8 @@ static struct clk_lookup lookups[] = {
|
|||
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1)
|
||||
_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk)
|
||||
_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
|
||||
_REGISTER_CLOCK(NULL, "vpu", vpu_clk)
|
||||
_REGISTER_CLOCK(NULL, "dma", dma_clk)
|
||||
|
|
|
@ -415,7 +415,7 @@ struct platform_device mxc_usbh2 = {
|
|||
}; \
|
||||
\
|
||||
struct platform_device imx_ssi_device ## n = { \
|
||||
.name = "imx-ssi", \
|
||||
.name = "imx-ssi-dai", \
|
||||
.id = n, \
|
||||
.num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \
|
||||
.resource = imx_ssi_resources ## n, \
|
||||
|
|
|
@ -558,8 +558,8 @@ static struct clk_lookup lookups[] = {
|
|||
_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
|
||||
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
|
||||
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK(NULL, "firi", firi_clk)
|
||||
_REGISTER_CLOCK(NULL, "ata", ata_clk)
|
||||
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
|
||||
|
|
|
@ -464,8 +464,8 @@ static struct clk_lookup lookups[] = {
|
|||
_REGISTER_CLOCK(NULL, "sdma", sdma_clk)
|
||||
_REGISTER_CLOCK(NULL, "spba", spba_clk)
|
||||
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.0", NULL, ssi1_clk)
|
||||
_REGISTER_CLOCK("imx-ssi-dai.1", NULL, ssi2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
|
||||
_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
|
||||
_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
|
||||
|
|
|
@ -562,14 +562,14 @@ static struct resource imx_ssi_resources1[] = {
|
|||
};
|
||||
|
||||
struct platform_device imx_ssi_device0 = {
|
||||
.name = "imx-ssi",
|
||||
.name = "imx-ssi-dai",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(imx_ssi_resources0),
|
||||
.resource = imx_ssi_resources0,
|
||||
};
|
||||
|
||||
struct platform_device imx_ssi_device1 = {
|
||||
.name = "imx-ssi",
|
||||
.name = "imx-ssi-dai",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(imx_ssi_resources1),
|
||||
.resource = imx_ssi_resources1,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <mach/gpio.h>
|
||||
#include <plat/mmc.h>
|
||||
#include <plat/omap7xx.h>
|
||||
#include <plat/mcbsp.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -267,6 +268,30 @@ static inline void omap_init_sti(void)
|
|||
static inline void omap_init_sti(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
|
||||
|
||||
static struct platform_device omap_pcm = {
|
||||
.name = "omap-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(1);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(2);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(3);
|
||||
|
||||
static void omap_init_audio(void)
|
||||
{
|
||||
platform_device_register(&omap_mcbsp1);
|
||||
platform_device_register(&omap_mcbsp2);
|
||||
if (!cpu_is_omap7xx())
|
||||
platform_device_register(&omap_mcbsp3);
|
||||
platform_device_register(&omap_pcm);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void omap_init_audio(void) {}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -299,6 +324,7 @@ static int __init omap1_init_devices(void)
|
|||
omap_init_rtc();
|
||||
omap_init_spi100k();
|
||||
omap_init_sti();
|
||||
omap_init_audio();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/usb/musb.h>
|
||||
#include <sound/tlv320aic3x.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -612,11 +613,25 @@ static int n8x0_menelaus_late_init(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct aic3x_setup_data n810_aic33_setup = {
|
||||
.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
|
||||
.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
|
||||
};
|
||||
|
||||
static struct aic3x_pdata n810_aic33_data = {
|
||||
.setup = &n810_aic33_setup,
|
||||
.gpio_reset = -1,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("menelaus", 0x72),
|
||||
.irq = INT_24XX_SYS_NIRQ,
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("tlv320aic3x", 0x1b),
|
||||
.platform_data = &n810_aic33_data,
|
||||
},
|
||||
};
|
||||
|
||||
static struct menelaus_platform_data n8x0_menelaus_platform_data = {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <sound/tlv320aic3x.h>
|
||||
|
||||
#include <plat/mcspi.h>
|
||||
#include <plat/mux.h>
|
||||
|
@ -686,7 +687,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
|
|||
};
|
||||
|
||||
|
||||
|
||||
static struct twl4030_platform_data rx51_twldata __initdata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
|
@ -716,9 +716,21 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/* Audio setup data */
|
||||
static struct aic3x_setup_data rx51_aic34_setup = {
|
||||
.gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
|
||||
.gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
|
||||
};
|
||||
|
||||
static struct aic3x_pdata rx51_aic34_data = {
|
||||
.setup = &rx51_aic34_setup,
|
||||
.gpio_reset = 60,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("tlv320aic3x", 0x18),
|
||||
.platform_data = &rx51_aic34_data,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
@ -34,8 +35,11 @@ static void __init omap_zoom2_init_irq(void)
|
|||
omap_gpio_init();
|
||||
}
|
||||
|
||||
/* REVISIT: These audio entries can be removed once MFD code is merged */
|
||||
#if 0
|
||||
/* EXTMUTE callback function */
|
||||
void zoom2_set_hs_extmute(int mute)
|
||||
{
|
||||
gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
|
||||
}
|
||||
|
||||
static struct twl4030_madc_platform_data zoom2_madc_data = {
|
||||
.irq_line = 1,
|
||||
|
@ -43,6 +47,9 @@ static struct twl4030_madc_platform_data zoom2_madc_data = {
|
|||
|
||||
static struct twl4030_codec_audio_data zoom2_audio_data = {
|
||||
.audio_mclk = 26000000,
|
||||
.ramp_delay_value = 3, /* 161 ms */
|
||||
.hs_extmute = 1,
|
||||
.set_hs_extmute = zoom2_set_hs_extmute,
|
||||
};
|
||||
|
||||
static struct twl4030_codec_data zoom2_codec_data = {
|
||||
|
@ -64,10 +71,24 @@ static struct twl4030_platform_data zoom2_twldata = {
|
|||
.vmmc1 = &zoom2_vmmc1,
|
||||
.vmmc2 = &zoom2_vmmc2,
|
||||
.vsim = &zoom2_vsim,
|
||||
|
||||
};
|
||||
|
||||
#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
|
||||
static struct omap_board_mux board_mux[] __initdata = {
|
||||
|
@ -81,6 +102,7 @@ static void __init omap_zoom2_init(void)
|
|||
{
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
zoom_peripherals_init();
|
||||
omap3_zoom2_i2c_init();
|
||||
zoom_debugboard_init();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <mach/gpio.h>
|
||||
#include <plat/mmc.h>
|
||||
#include <plat/dma.h>
|
||||
#include <plat/mcbsp.h>
|
||||
|
||||
#include "mux.h"
|
||||
|
||||
|
@ -289,6 +290,43 @@ static inline void omap_init_sti(void)
|
|||
static inline void omap_init_sti(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
|
||||
|
||||
static struct platform_device omap_pcm = {
|
||||
.name = "omap-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
/*
|
||||
* OMAP2420 has 2 McBSP ports
|
||||
* OMAP2430 has 5 McBSP ports
|
||||
* OMAP3 has 5 McBSP ports
|
||||
* OMAP4 has 4 McBSP ports
|
||||
*/
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(1);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(2);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(3);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(4);
|
||||
OMAP_MCBSP_PLATFORM_DEVICE(5);
|
||||
|
||||
static void omap_init_audio(void)
|
||||
{
|
||||
platform_device_register(&omap_mcbsp1);
|
||||
platform_device_register(&omap_mcbsp2);
|
||||
if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
|
||||
platform_device_register(&omap_mcbsp3);
|
||||
platform_device_register(&omap_mcbsp4);
|
||||
}
|
||||
if (cpu_is_omap243x() || cpu_is_omap34xx())
|
||||
platform_device_register(&omap_mcbsp5);
|
||||
|
||||
platform_device_register(&omap_pcm);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void omap_init_audio(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
|
||||
|
||||
#include <plat/mcspi.h>
|
||||
|
@ -901,6 +939,7 @@ static int __init omap2_init_devices(void)
|
|||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
omap_hsmmc_reset();
|
||||
omap_init_audio();
|
||||
omap_init_camera();
|
||||
omap_init_mbox();
|
||||
omap_init_mcspi();
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
*/
|
||||
extern int __init zoom_debugboard_init(void);
|
||||
extern void __init zoom_peripherals_init(void);
|
||||
|
||||
#define ZOOM2_HEADSET_EXTMUTE_GPIO 153
|
||||
|
|
|
@ -340,6 +340,31 @@ struct platform_device pxa_device_i2s = {
|
|||
.num_resources = ARRAY_SIZE(pxai2s_resources),
|
||||
};
|
||||
|
||||
struct platform_device pxa_device_asoc_ssp1 = {
|
||||
.name = "pxa-ssp-dai",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
struct platform_device pxa_device_asoc_ssp2= {
|
||||
.name = "pxa-ssp-dai",
|
||||
.id = 1,
|
||||
};
|
||||
|
||||
struct platform_device pxa_device_asoc_ssp3 = {
|
||||
.name = "pxa-ssp-dai",
|
||||
.id = 2,
|
||||
};
|
||||
|
||||
struct platform_device pxa_device_asoc_ssp4 = {
|
||||
.name = "pxa-ssp-dai",
|
||||
.id = 3,
|
||||
};
|
||||
|
||||
struct platform_device pxa_device_asoc_platform = {
|
||||
.name = "pxa-pcm-audio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static u64 pxaficp_dmamask = ~(u32)0;
|
||||
|
||||
struct platform_device pxa_device_ficp = {
|
||||
|
|
|
@ -37,4 +37,10 @@ extern struct platform_device pxa3xx_device_i2c_power;
|
|||
|
||||
extern struct platform_device pxa3xx_device_gcu;
|
||||
|
||||
extern struct platform_device pxa_device_asoc_platform;
|
||||
extern struct platform_device pxa_device_asoc_ssp1;
|
||||
extern struct platform_device pxa_device_asoc_ssp2;
|
||||
extern struct platform_device pxa_device_asoc_ssp3;
|
||||
extern struct platform_device pxa_device_asoc_ssp4;
|
||||
|
||||
void __init pxa_register_device(struct platform_device *dev, void *data);
|
||||
|
|
|
@ -384,6 +384,10 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
|
|||
static struct platform_device *devices[] __initdata = {
|
||||
&pxa27x_device_udc,
|
||||
&pxa_device_i2s,
|
||||
&pxa_device_asoc_ssp1,
|
||||
&pxa_device_asoc_ssp2,
|
||||
&pxa_device_asoc_ssp3,
|
||||
&pxa_device_asoc_platform,
|
||||
&sa1100_device_rtc,
|
||||
&pxa_device_rtc,
|
||||
&pxa27x_device_ssp1,
|
||||
|
|
|
@ -597,6 +597,11 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info)
|
|||
static struct platform_device *devices[] __initdata = {
|
||||
&pxa27x_device_udc,
|
||||
&pxa_device_i2s,
|
||||
&pxa_device_asoc_ssp1,
|
||||
&pxa_device_asoc_ssp2,
|
||||
&pxa_device_asoc_ssp3,
|
||||
&pxa_device_asoc_ssp4,
|
||||
&pxa_device_asoc_platform,
|
||||
&sa1100_device_rtc,
|
||||
&pxa_device_rtc,
|
||||
&pxa27x_device_ssp1,
|
||||
|
|
|
@ -45,6 +45,16 @@ int wm9713_irq;
|
|||
int lcd_id;
|
||||
int lcd_orientation;
|
||||
|
||||
struct platform_device pxa_device_wm9713_audio = {
|
||||
.name = "wm9713-codec",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static void __init zylonite_init_wm9713_audio(void)
|
||||
{
|
||||
platform_device_register(&pxa_device_wm9713_audio);
|
||||
}
|
||||
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = ZYLONITE_ETH_PHYS + 0x300,
|
||||
|
@ -408,6 +418,7 @@ static void __init zylonite_init(void)
|
|||
zylonite_init_nand();
|
||||
zylonite_init_leds();
|
||||
zylonite_init_ohci();
|
||||
zylonite_init_wm9713_audio();
|
||||
}
|
||||
|
||||
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
|
||||
|
|
|
@ -333,3 +333,16 @@ void __init s3c64xx_ac97_setup_gpio(int num)
|
|||
else
|
||||
s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
|
||||
}
|
||||
|
||||
static u64 s3c_device_audio_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device s3c_device_pcm = {
|
||||
.name = "s3c24xx-pcm-audio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL(s3c_device_pcm);
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
|
|||
&s3c_device_fb,
|
||||
&s3c_device_ohci,
|
||||
&s3c_device_usb_hsotg,
|
||||
&s3c_device_pcm,
|
||||
&s3c64xx_device_iisv4,
|
||||
|
||||
#ifdef CONFIG_REGULATOR
|
||||
|
|
|
@ -49,9 +49,9 @@ static const char *audmux_port_string(int port)
|
|||
{
|
||||
switch (port) {
|
||||
case MX31_AUDMUX_PORT1_SSI0:
|
||||
return "imx-ssi.0";
|
||||
return "imx-ssi-dai.0";
|
||||
case MX31_AUDMUX_PORT2_SSI1:
|
||||
return "imx-ssi.1";
|
||||
return "imx-ssi-dai.1";
|
||||
case MX31_AUDMUX_PORT3_SSI_PINS_3:
|
||||
return "SSI3";
|
||||
case MX31_AUDMUX_PORT4_SSI_PINS_4:
|
||||
|
|
|
@ -30,6 +30,13 @@
|
|||
#include <mach/hardware.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
/* macro for building platform_device for McBSP ports */
|
||||
#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
|
||||
static struct platform_device omap_mcbsp##port_nr = { \
|
||||
.name = "omap-mcbsp-dai", \
|
||||
.id = OMAP_MCBSP##port_nr, \
|
||||
}
|
||||
|
||||
#define OMAP7XX_MCBSP1_BASE 0xfffb1000
|
||||
#define OMAP7XX_MCBSP2_BASE 0xfffb1800
|
||||
|
||||
|
|
|
@ -481,7 +481,7 @@ static struct resource s3c_ac97_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static u64 s3c_device_ac97_dmamask = 0xffffffffUL;
|
||||
static u64 s3c_device_audio_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device s3c_device_ac97 = {
|
||||
.name = "s3c-ac97",
|
||||
|
@ -489,11 +489,37 @@ struct platform_device s3c_device_ac97 = {
|
|||
.num_resources = ARRAY_SIZE(s3c_ac97_resource),
|
||||
.resource = s3c_ac97_resource,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_ac97_dmamask,
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(s3c_device_ac97);
|
||||
|
||||
/* ASoC PCM DMA */
|
||||
|
||||
struct platform_device s3c_device_pcm = {
|
||||
.name = "s3c24xx-pcm-audio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(s3c_device_pcm);
|
||||
|
||||
/* ASoC I2S */
|
||||
|
||||
struct platform_device s3c2412_device_iis = {
|
||||
.name = "s3c2412-iis",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &s3c_device_audio_dmamask,
|
||||
.coherent_dma_mask = 0xffffffffUL
|
||||
}
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(s3c2412_device_iis);
|
||||
|
||||
#endif // CONFIG_CPU_S32440
|
||||
|
|
|
@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4;
|
|||
extern struct platform_device s3c64xx_device_spi0;
|
||||
extern struct platform_device s3c64xx_device_spi1;
|
||||
|
||||
extern struct platform_device s3c_device_pcm;
|
||||
|
||||
extern struct platform_device s3c64xx_device_pcm0;
|
||||
extern struct platform_device s3c64xx_device_pcm1;
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = {
|
|||
.probe = twl4030_vibra_probe,
|
||||
.remove = __devexit_p(twl4030_vibra_remove),
|
||||
.driver = {
|
||||
.name = "twl4030_codec_vibra",
|
||||
.name = "twl4030-vibra",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &twl4030_vibra_pm_ops,
|
||||
|
@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void)
|
|||
}
|
||||
module_exit(twl4030_vibra_exit);
|
||||
|
||||
MODULE_ALIAS("platform:twl4030_codec_vibra");
|
||||
MODULE_ALIAS("platform:twl4030-vibra");
|
||||
|
||||
MODULE_DESCRIPTION("TWL4030 Vibra driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
|
||||
if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
|
||||
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
|
||||
child = add_child(sub_chip_id, "twl4030_codec",
|
||||
child = add_child(sub_chip_id, "twl4030-audio",
|
||||
pdata->codec, sizeof(*pdata->codec),
|
||||
false, 0, 0);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
/* Phoenix*/
|
||||
/* Phoenix codec driver is probed directly atm */
|
||||
if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
|
||||
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
|
||||
child = add_child(sub_chip_id, "twl6040_codec",
|
||||
child = add_child(sub_chip_id, "twl6040-codec",
|
||||
pdata->codec, sizeof(*pdata->codec),
|
||||
false, 0, 0);
|
||||
if (IS_ERR(child))
|
||||
|
|
|
@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
|
|||
|
||||
if (pdata->audio) {
|
||||
cell = &codec->cells[childs];
|
||||
cell->name = "twl4030_codec_audio";
|
||||
cell->name = "twl4030-codec";
|
||||
cell->platform_data = pdata->audio;
|
||||
cell->data_size = sizeof(*pdata->audio);
|
||||
childs++;
|
||||
}
|
||||
if (pdata->vibra) {
|
||||
cell = &codec->cells[childs];
|
||||
cell->name = "twl4030_codec_vibra";
|
||||
cell->name = "twl4030-vibra";
|
||||
cell->platform_data = pdata->vibra;
|
||||
cell->data_size = sizeof(*pdata->vibra);
|
||||
childs++;
|
||||
|
@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:twl4030_codec");
|
||||
MODULE_ALIAS("platform:twl4030-audio");
|
||||
|
||||
static struct platform_driver twl4030_codec_driver = {
|
||||
.probe = twl4030_codec_probe,
|
||||
.remove = __devexit_p(twl4030_codec_remove),
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "twl4030_codec",
|
||||
.name = "twl4030-audio",
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
|||
extern int twl4030_remove_script(u8 flags);
|
||||
|
||||
struct twl4030_codec_audio_data {
|
||||
unsigned int audio_mclk;
|
||||
unsigned int audio_mclk; /* not used, will be removed */
|
||||
unsigned int digimic_delay; /* in ms */
|
||||
unsigned int ramp_delay_value;
|
||||
unsigned int offset_cncl_path;
|
||||
unsigned int check_defaults:1;
|
||||
unsigned int reset_registers:1;
|
||||
unsigned int hs_extmute:1;
|
||||
void (*set_hs_extmute)(int mute);
|
||||
};
|
||||
|
|
|
@ -114,7 +114,7 @@ struct sh_fsi_platform_info {
|
|||
int (*set_rate)(int is_porta, int rate); /* for master mode */
|
||||
};
|
||||
|
||||
extern struct snd_soc_dai fsi_soc_dai[2];
|
||||
extern struct snd_soc_platform fsi_soc_platform;
|
||||
extern struct snd_soc_dai_driver fsi_soc_dai[2];
|
||||
extern struct snd_soc_platform_driver fsi_soc_platform;
|
||||
|
||||
#endif /* __SOUND_FSI_H */
|
||||
|
|
|
@ -91,15 +91,17 @@ struct snd_pcm_substream;
|
|||
SNDRV_PCM_FMTBIT_S32_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_BE)
|
||||
|
||||
struct snd_soc_dai_ops;
|
||||
struct snd_soc_dai_driver;
|
||||
struct snd_soc_dai;
|
||||
struct snd_ac97_bus_ops;
|
||||
|
||||
/* Digital Audio Interface registration */
|
||||
int snd_soc_register_dai(struct snd_soc_dai *dai);
|
||||
void snd_soc_unregister_dai(struct snd_soc_dai *dai);
|
||||
int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
|
||||
void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
|
||||
int snd_soc_register_dai(struct device *dev,
|
||||
struct snd_soc_dai_driver *dai_drv);
|
||||
void snd_soc_unregister_dai(struct device *dev);
|
||||
int snd_soc_register_dais(struct device *dev,
|
||||
struct snd_soc_dai_driver *dai_drv, size_t count);
|
||||
void snd_soc_unregister_dais(struct device *dev, size_t count);
|
||||
|
||||
/* Digital Audio Interface clocking API.*/
|
||||
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
|
@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
|
|||
/* Digital Audio Interface mute */
|
||||
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
|
||||
|
||||
/*
|
||||
* Digital Audio Interface.
|
||||
*
|
||||
* Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
|
||||
* operations and capabilities. Codec and platform drivers will register this
|
||||
* structure for every DAI they have.
|
||||
*
|
||||
* This structure covers the clocking, formating and ALSA operations for each
|
||||
* interface.
|
||||
*/
|
||||
struct snd_soc_dai_ops {
|
||||
/*
|
||||
* DAI clocking configuration, all optional.
|
||||
|
@ -191,24 +183,24 @@ struct snd_soc_dai_ops {
|
|||
};
|
||||
|
||||
/*
|
||||
* Digital Audio Interface runtime data.
|
||||
* Digital Audio Interface Driver.
|
||||
*
|
||||
* Holds runtime data for a DAI.
|
||||
* Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
|
||||
* operations and capabilities. Codec and platform drivers will register this
|
||||
* structure for every DAI they have.
|
||||
*
|
||||
* This structure covers the clocking, formating and ALSA operations for each
|
||||
* interface.
|
||||
*/
|
||||
struct snd_soc_dai {
|
||||
struct snd_soc_dai_driver {
|
||||
/* DAI description */
|
||||
char *name;
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
int ac97_control;
|
||||
|
||||
struct device *dev;
|
||||
void *ac97_pdata; /* platform_data for the ac97 codec */
|
||||
|
||||
/* DAI callbacks */
|
||||
int (*probe)(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai);
|
||||
void (*remove)(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai);
|
||||
/* DAI driver callbacks */
|
||||
int (*probe)(struct snd_soc_dai *dai);
|
||||
int (*remove)(struct snd_soc_dai *dai);
|
||||
int (*suspend)(struct snd_soc_dai *dai);
|
||||
int (*resume)(struct snd_soc_dai *dai);
|
||||
|
||||
|
@ -219,26 +211,51 @@ struct snd_soc_dai {
|
|||
struct snd_soc_pcm_stream capture;
|
||||
struct snd_soc_pcm_stream playback;
|
||||
unsigned int symmetric_rates:1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Digital Audio Interface runtime data.
|
||||
*
|
||||
* Holds runtime data for a DAI.
|
||||
*/
|
||||
struct snd_soc_dai {
|
||||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
void *ac97_pdata; /* platform_data for the ac97 codec */
|
||||
|
||||
/* driver ops */
|
||||
struct snd_soc_dai_driver *driver;
|
||||
|
||||
/* DAI runtime info */
|
||||
struct snd_soc_codec *codec;
|
||||
unsigned int capture_active:1; /* stream is in use */
|
||||
unsigned int playback_active:1; /* stream is in use */
|
||||
unsigned int symmetric_rates:1;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
unsigned int active;
|
||||
unsigned char pop_wait:1;
|
||||
unsigned char probed:1;
|
||||
|
||||
/* DAI private data */
|
||||
void *private_data;
|
||||
/* DAI DMA data */
|
||||
void *playback_dma_data;
|
||||
void *capture_dma_data;
|
||||
|
||||
/* parent platform */
|
||||
/* parent platform/codec */
|
||||
union {
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_codec *codec;
|
||||
};
|
||||
struct snd_soc_card *card;
|
||||
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
};
|
||||
|
||||
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
|
||||
const struct snd_pcm_substream *ss)
|
||||
{
|
||||
return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
dai->playback.dma_data : dai->capture.dma_data;
|
||||
dai->playback_dma_data : dai->capture_dma_data;
|
||||
}
|
||||
|
||||
static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
|
||||
|
@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
|
|||
void *data)
|
||||
{
|
||||
if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dai->playback.dma_data = data;
|
||||
dai->playback_dma_data = data;
|
||||
else
|
||||
dai->capture.dma_data = data;
|
||||
dai->capture_dma_data = data;
|
||||
}
|
||||
|
||||
static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(dai->dev, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai)
|
||||
{
|
||||
return dev_get_drvdata(dai->dev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -322,14 +322,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
|
|||
|
||||
/* dapm path setup */
|
||||
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_free(struct snd_soc_device *socdev);
|
||||
void snd_soc_dapm_free(struct snd_soc_codec *codec);
|
||||
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
|
||||
const struct snd_soc_dapm_route *route, int num);
|
||||
|
||||
/* dapm events */
|
||||
int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
|
||||
int event);
|
||||
void snd_soc_dapm_shutdown(struct snd_soc_device *socdev);
|
||||
int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
|
||||
const char *stream, int event);
|
||||
void snd_soc_dapm_shutdown(struct snd_soc_card *card);
|
||||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
|
|
|
@ -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_ */
|
|
@ -228,13 +228,17 @@ struct snd_soc_ops;
|
|||
struct snd_soc_dai_mode;
|
||||
struct snd_soc_pcm_runtime;
|
||||
struct snd_soc_dai;
|
||||
struct snd_soc_dai_driver;
|
||||
struct snd_soc_platform;
|
||||
struct snd_soc_dai_link;
|
||||
struct snd_soc_platform_driver;
|
||||
struct snd_soc_codec;
|
||||
struct snd_soc_codec_driver;
|
||||
struct soc_enum;
|
||||
struct snd_soc_ac97_ops;
|
||||
struct snd_soc_jack;
|
||||
struct snd_soc_jack_pin;
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct snd_soc_jack_gpio;
|
||||
#endif
|
||||
|
@ -249,19 +253,18 @@ enum snd_soc_control_type {
|
|||
SND_SOC_SPI,
|
||||
};
|
||||
|
||||
int snd_soc_register_platform(struct snd_soc_platform *platform);
|
||||
void snd_soc_unregister_platform(struct snd_soc_platform *platform);
|
||||
int snd_soc_register_codec(struct snd_soc_codec *codec);
|
||||
void snd_soc_unregister_codec(struct snd_soc_codec *codec);
|
||||
int snd_soc_register_platform(struct device *dev,
|
||||
struct snd_soc_platform_driver *platform_drv);
|
||||
void snd_soc_unregister_platform(struct device *dev);
|
||||
int snd_soc_register_codec(struct device *dev,
|
||||
struct snd_soc_codec_driver *codec_drv,
|
||||
struct snd_soc_dai_driver *dai_drv, int num_dai);
|
||||
void snd_soc_unregister_codec(struct device *dev);
|
||||
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
|
||||
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
|
||||
int addr_bits, int data_bits,
|
||||
enum snd_soc_control_type control);
|
||||
|
||||
/* pcm <-> DAI connect */
|
||||
void snd_soc_free_pcms(struct snd_soc_device *socdev);
|
||||
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
|
||||
|
||||
/* Utility functions to get clock rates from various things */
|
||||
int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
|
||||
int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
|
||||
|
@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
|
|||
const struct snd_pcm_hardware *hw);
|
||||
|
||||
/* Jack reporting */
|
||||
int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
|
||||
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
||||
struct snd_soc_jack *jack);
|
||||
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
|
||||
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
|
||||
|
@ -390,7 +393,7 @@ struct snd_soc_jack_gpio {
|
|||
|
||||
struct snd_soc_jack {
|
||||
struct snd_jack *jack;
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_codec *codec;
|
||||
struct list_head pins;
|
||||
int status;
|
||||
struct blocking_notifier_head notifier;
|
||||
|
@ -398,15 +401,13 @@ struct snd_soc_jack {
|
|||
|
||||
/* SoC PCM stream information */
|
||||
struct snd_soc_pcm_stream {
|
||||
char *stream_name;
|
||||
const char *stream_name;
|
||||
u64 formats; /* SNDRV_PCM_FMTBIT_* */
|
||||
unsigned int rates; /* SNDRV_PCM_RATE_* */
|
||||
unsigned int rate_min; /* min rate */
|
||||
unsigned int rate_max; /* max rate */
|
||||
unsigned int channels_min; /* min channels */
|
||||
unsigned int channels_max; /* max channels */
|
||||
unsigned int active; /* stream is in use */
|
||||
void *dma_data; /* used by platform code */
|
||||
};
|
||||
|
||||
/* SoC audio ops */
|
||||
|
@ -419,44 +420,35 @@ struct snd_soc_ops {
|
|||
int (*trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
/* SoC Audio Codec */
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
char *name;
|
||||
struct module *owner;
|
||||
struct mutex mutex;
|
||||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
struct snd_soc_device *socdev;
|
||||
struct snd_soc_codec_driver *driver;
|
||||
|
||||
struct mutex mutex;
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
|
||||
/* callbacks */
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
enum snd_soc_bias_level level);
|
||||
struct list_head card_list;
|
||||
int num_dai;
|
||||
|
||||
/* runtime */
|
||||
struct snd_card *card;
|
||||
struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
|
||||
unsigned int active;
|
||||
unsigned int pcm_devs;
|
||||
void *drvdata;
|
||||
|
||||
/* codec IO */
|
||||
void *control_data; /* codec control (i2c/3wire) data */
|
||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||
int (*display_register)(struct snd_soc_codec *, char *,
|
||||
size_t, unsigned int);
|
||||
int (*volatile_register)(unsigned int);
|
||||
int (*readable_register)(unsigned int);
|
||||
hw_write_t hw_write;
|
||||
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
|
||||
void *reg_cache;
|
||||
short reg_cache_size;
|
||||
short reg_cache_step;
|
||||
|
||||
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
|
||||
unsigned int cache_only:1; /* Suppress writes to hardware */
|
||||
unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
|
||||
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 */
|
||||
u32 pop_time;
|
||||
|
@ -466,10 +458,6 @@ struct snd_soc_codec {
|
|||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
|
||||
/* codec DAI's */
|
||||
struct snd_soc_dai *dai;
|
||||
unsigned int num_dai;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_codec_root;
|
||||
struct dentry *debugfs_reg;
|
||||
|
@ -478,23 +466,40 @@ struct snd_soc_codec {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* codec device */
|
||||
struct snd_soc_codec_device {
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
int (*suspend)(struct platform_device *pdev, pm_message_t state);
|
||||
int (*resume)(struct platform_device *pdev);
|
||||
/* codec driver */
|
||||
struct snd_soc_codec_driver {
|
||||
|
||||
/* driver ops */
|
||||
int (*probe)(struct snd_soc_codec *);
|
||||
int (*remove)(struct snd_soc_codec *);
|
||||
int (*suspend)(struct snd_soc_codec *,
|
||||
pm_message_t state);
|
||||
int (*resume)(struct snd_soc_codec *);
|
||||
|
||||
/* codec IO */
|
||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||
int (*display_register)(struct snd_soc_codec *, char *,
|
||||
size_t, unsigned int);
|
||||
int (*volatile_register)(unsigned int);
|
||||
int (*readable_register)(unsigned int);
|
||||
short reg_cache_size;
|
||||
short reg_cache_step;
|
||||
short reg_word_size;
|
||||
const void *reg_cache_default;
|
||||
|
||||
/* codec bias level */
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
enum snd_soc_bias_level level);
|
||||
};
|
||||
|
||||
/* SoC platform interface */
|
||||
struct snd_soc_platform {
|
||||
char *name;
|
||||
struct list_head list;
|
||||
struct snd_soc_platform_driver {
|
||||
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
int (*suspend)(struct snd_soc_dai_link *dai_link);
|
||||
int (*resume)(struct snd_soc_dai_link *dai_link);
|
||||
int (*probe)(struct snd_soc_platform *);
|
||||
int (*remove)(struct snd_soc_platform *);
|
||||
int (*suspend)(struct snd_soc_dai *dai);
|
||||
int (*resume)(struct snd_soc_dai *dai);
|
||||
|
||||
/* pcm creation and destruction */
|
||||
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
|
||||
|
@ -509,23 +514,31 @@ struct snd_soc_platform {
|
|||
struct snd_soc_dai *);
|
||||
|
||||
/* platform stream ops */
|
||||
struct snd_pcm_ops *pcm_ops;
|
||||
struct snd_pcm_ops *ops;
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
const char *name;
|
||||
int id;
|
||||
struct device *dev;
|
||||
struct snd_soc_platform_driver *driver;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
unsigned int probed:1;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
};
|
||||
|
||||
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
|
||||
struct snd_soc_dai_link {
|
||||
char *name; /* Codec name */
|
||||
char *stream_name; /* Stream name */
|
||||
|
||||
/* DAI */
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
/* machine stream operations */
|
||||
struct snd_soc_ops *ops;
|
||||
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
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 */
|
||||
unsigned int ignore_suspend:1;
|
||||
|
@ -533,21 +546,24 @@ struct snd_soc_dai_link {
|
|||
/* Symmetry requirements */
|
||||
unsigned int symmetric_rates:1;
|
||||
|
||||
/* Symmetry data - only valid if symmetry is being enforced */
|
||||
unsigned int rate;
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
int (*init)(struct snd_soc_pcm_runtime *rtd);
|
||||
|
||||
/* DAI pcm */
|
||||
struct snd_pcm *pcm;
|
||||
/* machine stream operations */
|
||||
struct snd_soc_ops *ops;
|
||||
};
|
||||
|
||||
/* SoC card */
|
||||
struct snd_soc_card {
|
||||
char *name;
|
||||
const char *name;
|
||||
struct device *dev;
|
||||
struct snd_card *snd_card;
|
||||
struct module *owner;
|
||||
|
||||
struct list_head list;
|
||||
struct mutex mutex;
|
||||
|
||||
int instantiated;
|
||||
bool instantiated;
|
||||
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
|
@ -568,28 +584,38 @@ struct snd_soc_card {
|
|||
/* CPU <--> Codec DAI links */
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int num_links;
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
int num_rtd;
|
||||
|
||||
struct snd_soc_device *socdev;
|
||||
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
struct snd_soc_platform *platform;
|
||||
struct delayed_work delayed_work;
|
||||
struct work_struct deferred_resume_work;
|
||||
|
||||
/* lists of probed devices belonging to this card */
|
||||
struct list_head codec_dev_list;
|
||||
struct list_head platform_dev_list;
|
||||
struct list_head dai_dev_list;
|
||||
};
|
||||
|
||||
/* SoC Device - the audio subsystem */
|
||||
struct snd_soc_device {
|
||||
struct device *dev;
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_codec_device *codec_dev;
|
||||
void *codec_data;
|
||||
};
|
||||
|
||||
/* runtime channel data */
|
||||
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
|
||||
struct snd_soc_pcm_runtime {
|
||||
struct snd_soc_dai_link *dai;
|
||||
struct snd_soc_device *socdev;
|
||||
struct device dev;
|
||||
struct snd_soc_card *card;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
|
||||
unsigned int complete:1;
|
||||
unsigned int dev_registered:1;
|
||||
|
||||
/* Symmetry data - only valid if symmetry is being enforced */
|
||||
unsigned int rate;
|
||||
long pmdown_time;
|
||||
|
||||
/* runtime devices */
|
||||
struct snd_pcm *pcm;
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_platform *platform;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
};
|
||||
|
||||
/* mixer control */
|
||||
|
@ -615,24 +641,48 @@ struct soc_enum {
|
|||
static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
return codec->read(codec, reg);
|
||||
return codec->driver->read(codec, reg);
|
||||
}
|
||||
|
||||
static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
|
||||
unsigned int reg, unsigned int val)
|
||||
{
|
||||
return codec->write(codec, reg, val);
|
||||
return codec->driver->write(codec, reg, val);
|
||||
}
|
||||
|
||||
/* device driver data */
|
||||
|
||||
static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
|
||||
void *data)
|
||||
{
|
||||
codec->drvdata = data;
|
||||
dev_set_drvdata(codec->dev, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
|
||||
{
|
||||
return codec->drvdata;
|
||||
return dev_get_drvdata(codec->dev);
|
||||
}
|
||||
|
||||
static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(platform->dev, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
|
||||
{
|
||||
return dev_get_drvdata(platform->dev);
|
||||
}
|
||||
|
||||
static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd,
|
||||
void *data)
|
||||
{
|
||||
dev_set_drvdata(&rtd->dev, data);
|
||||
}
|
||||
|
||||
static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
return dev_get_drvdata(&rtd->dev);
|
||||
}
|
||||
|
||||
#include <sound/soc-dai.h>
|
||||
|
|
|
@ -10,8 +10,49 @@
|
|||
#ifndef __TLV320AIC3x_H__
|
||||
#define __TLV320AIC3x_H__
|
||||
|
||||
/* GPIO API */
|
||||
enum {
|
||||
AIC3X_GPIO1_FUNC_DISABLED = 0,
|
||||
AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1,
|
||||
AIC3X_GPIO1_FUNC_CLOCK_MUX = 2,
|
||||
AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3,
|
||||
AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4,
|
||||
AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5,
|
||||
AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6,
|
||||
AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7,
|
||||
AIC3X_GPIO1_FUNC_INPUT = 8,
|
||||
AIC3X_GPIO1_FUNC_OUTPUT = 9,
|
||||
AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10,
|
||||
AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11,
|
||||
AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12,
|
||||
AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13,
|
||||
AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14,
|
||||
AIC3X_GPIO1_FUNC_ALL_IRQ = 16
|
||||
};
|
||||
|
||||
enum {
|
||||
AIC3X_GPIO2_FUNC_DISABLED = 0,
|
||||
AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2,
|
||||
AIC3X_GPIO2_FUNC_INPUT = 3,
|
||||
AIC3X_GPIO2_FUNC_OUTPUT = 4,
|
||||
AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5,
|
||||
AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8,
|
||||
AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
|
||||
AIC3X_GPIO2_FUNC_ALL_IRQ = 10,
|
||||
AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
|
||||
AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
|
||||
AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13,
|
||||
AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14,
|
||||
AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
|
||||
};
|
||||
|
||||
struct aic3x_setup_data {
|
||||
unsigned int gpio_func[2];
|
||||
};
|
||||
|
||||
struct aic3x_pdata {
|
||||
int gpio_reset; /* < 0 if not used */
|
||||
struct aic3x_setup_data *setup;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
runtime->dma_bytes = params_buffer_bytes(params);
|
||||
|
||||
prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||
prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
|
||||
|
||||
prtd->dma_buffer = runtime->dma_addr;
|
||||
|
@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card,
|
|||
if (!card->dev->coherent_dma_mask)
|
||||
card->dev->coherent_dma_mask = 0xffffffff;
|
||||
|
||||
if (dai->playback.channels_min) {
|
||||
if (dai->driver->playback.channels_min) {
|
||||
ret = atmel_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dai->capture.channels_min) {
|
||||
if (dai->driver->capture.channels_min) {
|
||||
pr_debug("at32-pcm:"
|
||||
"Allocating PCM capture DMA buffer\n");
|
||||
ret = atmel_pcm_preallocate_dma_buffer(pcm,
|
||||
|
@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
|
||||
static int atmel_pcm_suspend(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_pcm *pcm = dai_link->pcm;
|
||||
struct snd_pcm_str *stream = &pcm->streams[0];
|
||||
struct snd_pcm_substream *substream = stream->substream;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_runtime *runtime = dai->runtime;
|
||||
struct atmel_runtime_data *prtd;
|
||||
struct atmel_pcm_dma_params *params;
|
||||
|
||||
|
@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
|
||||
static int atmel_pcm_resume(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_pcm *pcm = dai_link->pcm;
|
||||
struct snd_pcm_str *stream = &pcm->streams[0];
|
||||
struct snd_pcm_substream *substream = stream->substream;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_runtime *runtime = dai->runtime;
|
||||
struct atmel_runtime_data *prtd;
|
||||
struct atmel_pcm_dma_params *params;
|
||||
|
||||
|
@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
|
|||
#define atmel_pcm_resume NULL
|
||||
#endif
|
||||
|
||||
struct snd_soc_platform atmel_soc_platform = {
|
||||
.name = "atmel-audio",
|
||||
.pcm_ops = &atmel_pcm_ops,
|
||||
static struct snd_soc_platform_driver atmel_soc_platform = {
|
||||
.ops = &atmel_pcm_ops,
|
||||
.pcm_new = atmel_pcm_new,
|
||||
.pcm_free = atmel_pcm_free_dma_buffers,
|
||||
.suspend = atmel_pcm_suspend,
|
||||
.resume = atmel_pcm_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(atmel_soc_platform);
|
||||
|
||||
static int __init atmel_pcm_modinit(void)
|
||||
static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_platform(&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_DESCRIPTION("Atmel PCM module");
|
||||
|
|
|
@ -74,9 +74,6 @@ struct atmel_pcm_dma_params {
|
|||
void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
extern struct snd_soc_platform atmel_soc_platform;
|
||||
|
||||
|
||||
/*
|
||||
* SSC register access (since ssc_writel() / ssc_readl() require literal name)
|
||||
*/
|
||||
|
|
|
@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
|
|||
static int atmel_ssc_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||
int dir_mask;
|
||||
|
||||
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
|
||||
|
@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
|
|||
static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
int dir, dir_mask;
|
||||
|
||||
|
@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
||||
int id = rtd->dai->cpu_dai->id;
|
||||
int id = dai->id;
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[id];
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
int dir, channels, bits;
|
||||
|
@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
* function. It should not be used for other purposes
|
||||
* as it is common to all substreams.
|
||||
*/
|
||||
snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params);
|
||||
snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
|
||||
|
||||
channels = params_channels(params);
|
||||
|
||||
|
@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||
static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||
struct atmel_pcm_dma_params *dma_params;
|
||||
int dir;
|
||||
|
||||
|
@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
|
|||
# define atmel_ssc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static int atmel_ssc_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||
int ret = 0;
|
||||
|
||||
snd_soc_dai_set_drvdata(dai, ssc_p);
|
||||
|
||||
/*
|
||||
* Request SSC device
|
||||
*/
|
||||
ssc_p->ssc = ssc_request(dai->id);
|
||||
if (IS_ERR(ssc_p->ssc)) {
|
||||
printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
|
||||
ret = PTR_ERR(ssc_p->ssc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atmel_ssc_remove(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
ssc_free(ssc_p->ssc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
|
||||
|
||||
|
@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
|
|||
.set_clkdiv = atmel_ssc_set_dai_clkdiv,
|
||||
};
|
||||
|
||||
struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
|
||||
{ .name = "atmel-ssc0",
|
||||
.id = 0,
|
||||
static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
|
||||
{
|
||||
.name = "atmel-ssc-dai.0",
|
||||
.probe = atmel_ssc_probe,
|
||||
.remove = atmel_ssc_remove,
|
||||
.suspend = atmel_ssc_suspend,
|
||||
.resume = atmel_ssc_resume,
|
||||
.playback = {
|
||||
|
@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
|
|||
.rates = ATMEL_SSC_RATES,
|
||||
.formats = ATMEL_SSC_FORMATS,},
|
||||
.ops = &atmel_ssc_dai_ops,
|
||||
.private_data = &ssc_info[0],
|
||||
},
|
||||
#if NUM_SSC_DEVICES == 3
|
||||
{ .name = "atmel-ssc1",
|
||||
.id = 1,
|
||||
{
|
||||
.name = "atmel-ssc-dai.1",
|
||||
.probe = atmel_ssc_probe,
|
||||
.remove = atmel_ssc_remove,
|
||||
.suspend = atmel_ssc_suspend,
|
||||
.resume = atmel_ssc_resume,
|
||||
.playback = {
|
||||
|
@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
|
|||
.rates = ATMEL_SSC_RATES,
|
||||
.formats = ATMEL_SSC_FORMATS,},
|
||||
.ops = &atmel_ssc_dai_ops,
|
||||
.private_data = &ssc_info[1],
|
||||
},
|
||||
{ .name = "atmel-ssc2",
|
||||
.id = 2,
|
||||
{
|
||||
.name = "atmel-ssc-dai.2",
|
||||
.probe = atmel_ssc_probe,
|
||||
.remove = atmel_ssc_remove,
|
||||
.suspend = atmel_ssc_suspend,
|
||||
.resume = atmel_ssc_resume,
|
||||
.playback = {
|
||||
|
@ -756,23 +783,43 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
|
|||
.rates = ATMEL_SSC_RATES,
|
||||
.formats = ATMEL_SSC_FORMATS,},
|
||||
.ops = &atmel_ssc_dai_ops,
|
||||
.private_data = &ssc_info[2],
|
||||
},
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(atmel_ssc_dai);
|
||||
|
||||
static int __init atmel_ssc_modinit(void)
|
||||
static __devinit int asoc_ssc_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_dais(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_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
|
||||
|
|
|
@ -116,6 +116,5 @@ struct atmel_ssc_info {
|
|||
struct atmel_pcm_dma_params *dma_params[2];
|
||||
struct atmel_ssc_state ssc_state;
|
||||
};
|
||||
extern struct snd_soc_dai atmel_ssc_dai[];
|
||||
|
||||
#endif /* _AT91_SSC_DAI_H */
|
||||
|
|
|
@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
|
|||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct at32_ssc_info *ssc_p = cpu_dai->private_data;
|
||||
struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
struct ssc_device *ssc = ssc_p->ssc;
|
||||
struct ssc_clock_data cd;
|
||||
unsigned int rate, width_bits, channels;
|
||||
|
@ -131,9 +131,9 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct at32_ssc_info *ssc_p = cpu_dai->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
struct ssc_device *ssc = ssc_p->ssc;
|
||||
unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
|
||||
int ret;
|
||||
|
@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
|
||||
|
||||
|
||||
static int playpaq_wm8510_init(struct snd_soc_codec *codec)
|
||||
static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
int i;
|
||||
|
||||
/*
|
||||
|
@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
|
|||
|
||||
|
||||
/* Make CSB show PLL rate */
|
||||
snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV,
|
||||
snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
|
||||
WM8510_OPCLKDIV_1 | 4);
|
||||
|
||||
return 0;
|
||||
|
@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
|
|||
static struct snd_soc_dai_link playpaq_wm8510_dai = {
|
||||
.name = "WM8510",
|
||||
.stream_name = "WM8510 PCM",
|
||||
.cpu_dai = &at32_ssc_dai[0],
|
||||
.codec_dai = &wm8510_dai,
|
||||
.cpu_dai_name= "atmel-ssc-dai.0",
|
||||
.platform_name = "atmel-pcm-audio",
|
||||
.codec_name = "wm8510-codec.0-0x1a",
|
||||
.codec_dai_name = "wm8510-hifi",
|
||||
.init = playpaq_wm8510_init,
|
||||
.ops = &playpaq_wm8510_ops,
|
||||
};
|
||||
|
@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
|
|||
|
||||
static struct snd_soc_card snd_soc_playpaq = {
|
||||
.name = "LRS_PlayPaq_WM8510",
|
||||
.platform = &at32_soc_platform,
|
||||
.dai_link = &playpaq_wm8510_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct wm8510_setup_data playpaq_wm8510_setup = {
|
||||
.i2c_bus = 0,
|
||||
.i2c_address = 0x1a,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct snd_soc_device playpaq_wm8510_snd_devdata = {
|
||||
.card = &snd_soc_playpaq,
|
||||
.codec_dev = &soc_codec_dev_wm8510,
|
||||
.codec_data = &playpaq_wm8510_setup,
|
||||
};
|
||||
|
||||
static struct platform_device *playpaq_snd_device;
|
||||
|
||||
|
||||
static int __init playpaq_asoc_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
|
||||
struct ssc_device *ssc = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Request SSC device
|
||||
*/
|
||||
ssc = ssc_request(0);
|
||||
if (IS_ERR(ssc)) {
|
||||
ret = PTR_ERR(ssc);
|
||||
goto err_ssc;
|
||||
}
|
||||
ssc_p->ssc = ssc;
|
||||
|
||||
|
||||
/*
|
||||
* Configure MCLK for WM8510
|
||||
|
@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void)
|
|||
goto err_device_alloc;
|
||||
}
|
||||
|
||||
platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata);
|
||||
playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
|
||||
platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
|
||||
|
||||
ret = platform_device_add(playpaq_snd_device);
|
||||
if (ret) {
|
||||
|
@ -468,25 +440,12 @@ err_pll0:
|
|||
clk_put(_gclk0);
|
||||
_gclk0 = NULL;
|
||||
}
|
||||
err_gclk0:
|
||||
ssc_free(ssc);
|
||||
err_ssc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void __exit playpaq_asoc_exit(void)
|
||||
{
|
||||
struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
|
||||
struct ssc_device *ssc;
|
||||
|
||||
if (ssc_p != NULL) {
|
||||
ssc = ssc_p->ssc;
|
||||
if (ssc != NULL)
|
||||
ssc_free(ssc);
|
||||
ssc_p->ssc = NULL;
|
||||
}
|
||||
|
||||
if (_gclk0 != NULL) {
|
||||
clk_put(_gclk0);
|
||||
_gclk0 = NULL;
|
||||
|
|
|
@ -69,8 +69,8 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int ret;
|
||||
|
||||
/* set codec DAI configuration */
|
||||
|
@ -136,9 +136,10 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
/*
|
||||
* Logic for a wm8731 as connected on a at91sam9g20ek board.
|
||||
*/
|
||||
static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
|
||||
static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai = &codec->dai[0];
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret;
|
||||
|
||||
printk(KERN_DEBUG
|
||||
|
@ -179,31 +180,25 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
|
|||
static struct snd_soc_dai_link at91sam9g20ek_dai = {
|
||||
.name = "WM8731",
|
||||
.stream_name = "WM8731 PCM",
|
||||
.cpu_dai = &atmel_ssc_dai[0],
|
||||
.codec_dai = &wm8731_dai,
|
||||
.cpu_dai_name = "atmel-ssc-dai.0",
|
||||
.codec_dai_name = "wm8731-hifi",
|
||||
.init = at91sam9g20ek_wm8731_init,
|
||||
.platform_name = "atmel_pcm-audio",
|
||||
.codec_name = "wm8731-codec.0-001a",
|
||||
.ops = &at91sam9g20ek_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card snd_soc_at91sam9g20ek = {
|
||||
.name = "AT91SAMG20-EK",
|
||||
.platform = &atmel_soc_platform,
|
||||
.dai_link = &at91sam9g20ek_dai,
|
||||
.num_links = 1,
|
||||
.set_bias_level = at91sam9g20ek_set_bias_level,
|
||||
};
|
||||
|
||||
static struct snd_soc_device at91sam9g20ek_snd_devdata = {
|
||||
.card = &snd_soc_at91sam9g20ek,
|
||||
.codec_dev = &soc_codec_dev_wm8731,
|
||||
};
|
||||
|
||||
static struct platform_device *at91sam9g20ek_snd_device;
|
||||
|
||||
static int __init at91sam9g20ek_init(void)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
|
||||
struct ssc_device *ssc = NULL;
|
||||
struct clk *pllb;
|
||||
int ret;
|
||||
|
||||
|
@ -235,18 +230,6 @@ static int __init at91sam9g20ek_init(void)
|
|||
|
||||
clk_set_rate(mclk, MCLK_RATE);
|
||||
|
||||
/*
|
||||
* Request SSC device
|
||||
*/
|
||||
ssc = ssc_request(0);
|
||||
if (IS_ERR(ssc)) {
|
||||
printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
|
||||
ret = PTR_ERR(ssc);
|
||||
ssc = NULL;
|
||||
goto err_ssc;
|
||||
}
|
||||
ssc_p->ssc = ssc;
|
||||
|
||||
at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!at91sam9g20ek_snd_device) {
|
||||
printk(KERN_ERR "ASoC: Platform device allocation failed\n");
|
||||
|
@ -254,8 +237,7 @@ static int __init at91sam9g20ek_init(void)
|
|||
}
|
||||
|
||||
platform_set_drvdata(at91sam9g20ek_snd_device,
|
||||
&at91sam9g20ek_snd_devdata);
|
||||
at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
|
||||
&snd_soc_at91sam9g20ek);
|
||||
|
||||
ret = platform_device_add(at91sam9g20ek_snd_device);
|
||||
if (ret) {
|
||||
|
@ -265,9 +247,6 @@ static int __init at91sam9g20ek_init(void)
|
|||
|
||||
return ret;
|
||||
|
||||
err_ssc:
|
||||
ssc_free(ssc);
|
||||
ssc_p->ssc = NULL;
|
||||
err_mclk:
|
||||
clk_put(mclk);
|
||||
mclk = NULL;
|
||||
|
@ -277,16 +256,6 @@ err:
|
|||
|
||||
static void __exit at91sam9g20ek_exit(void)
|
||||
{
|
||||
struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
|
||||
struct ssc_device *ssc;
|
||||
|
||||
if (ssc_p != NULL) {
|
||||
ssc = ssc_p->ssc;
|
||||
if (ssc != NULL)
|
||||
ssc_free(ssc);
|
||||
ssc_p->ssc = NULL;
|
||||
}
|
||||
|
||||
platform_device_unregister(at91sam9g20ek_snd_device);
|
||||
at91sam9g20ek_snd_device = NULL;
|
||||
clk_put(mclk);
|
||||
|
|
|
@ -46,8 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int err;
|
||||
|
||||
/* Set codec DAI configuration */
|
||||
|
@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
|
|||
{"MICIN", NULL, "Mic Jack"},
|
||||
};
|
||||
|
||||
static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
|
||||
static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
|
||||
/* Add afeb9260 specific widgets */
|
||||
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
|
||||
|
@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
|
|||
static struct snd_soc_dai_link afeb9260_dai = {
|
||||
.name = "TLV320AIC23",
|
||||
.stream_name = "AIC23",
|
||||
.cpu_dai = &atmel_ssc_dai[0],
|
||||
.codec_dai = &tlv320aic23_dai,
|
||||
.cpu_dai_name = "atmel-ssc-dai.0",
|
||||
.codec_dai_name = "tlv320aic23-hifi",
|
||||
.platform_name = "atmel_pcm-audio",
|
||||
.codec_name = "tlv320aic23-codec.0-0x1a",
|
||||
.init = afeb9260_tlv320aic23_init,
|
||||
.ops = &afeb9260_ops,
|
||||
};
|
||||
|
@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = {
|
|||
/* Audio machine driver */
|
||||
static struct snd_soc_card snd_soc_machine_afeb9260 = {
|
||||
.name = "AFEB9260",
|
||||
.platform = &atmel_soc_platform,
|
||||
.dai_link = &afeb9260_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
/* Audio subsystem */
|
||||
static struct snd_soc_device afeb9260_snd_devdata = {
|
||||
.card = &snd_soc_machine_afeb9260,
|
||||
.codec_dev = &soc_codec_dev_tlv320aic23,
|
||||
};
|
||||
|
||||
static struct platform_device *afeb9260_snd_device;
|
||||
|
||||
static int __init afeb9260_soc_init(void)
|
||||
{
|
||||
int err;
|
||||
struct device *dev;
|
||||
struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data;
|
||||
struct ssc_device *ssc = NULL;
|
||||
|
||||
if (!(machine_is_afeb9260()))
|
||||
return -ENODEV;
|
||||
|
||||
ssc = ssc_request(0);
|
||||
if (IS_ERR(ssc)) {
|
||||
printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
|
||||
err = PTR_ERR(ssc);
|
||||
ssc = NULL;
|
||||
goto err_ssc;
|
||||
}
|
||||
ssc_p->ssc = ssc;
|
||||
|
||||
afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!afeb9260_snd_device) {
|
||||
|
@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata);
|
||||
afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev;
|
||||
platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);
|
||||
err = platform_device_add(afeb9260_snd_device);
|
||||
if (err)
|
||||
goto err1;
|
||||
|
@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void)
|
|||
err1:
|
||||
platform_device_del(afeb9260_snd_device);
|
||||
platform_device_put(afeb9260_snd_device);
|
||||
err_ssc:
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static void __exit afeb9260_soc_exit(void)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <asm/mach-au1x00/au1xxx_dbdma.h>
|
||||
#include <asm/mach-db1x00/bcsr.h>
|
||||
|
||||
#include "../codecs/ac97.h"
|
||||
#include "../codecs/wm8731.h"
|
||||
#include "psc.h"
|
||||
|
||||
|
@ -28,20 +27,16 @@
|
|||
static struct snd_soc_dai_link db1200_ac97_dai = {
|
||||
.name = "AC97",
|
||||
.stream_name = "AC97 HiFi",
|
||||
.cpu_dai = &au1xpsc_ac97_dai,
|
||||
.codec_dai = &ac97_dai,
|
||||
.cpu_dai_name = "au1xpsc-ac97",
|
||||
.codec_dai_name = "ac97-hifi",
|
||||
.platform_name = "au1xpsc-pcm-audio",
|
||||
.codec_name = "ac97-codec",
|
||||
};
|
||||
|
||||
static struct snd_soc_card db1200_ac97_machine = {
|
||||
.name = "DB1200_AC97",
|
||||
.dai_link = &db1200_ac97_dai,
|
||||
.num_links = 1,
|
||||
.platform = &au1xpsc_soc_platform,
|
||||
};
|
||||
|
||||
static struct snd_soc_device db1200_ac97_devdata = {
|
||||
.card = &db1200_ac97_machine,
|
||||
.codec_dev = &soc_codec_dev_ac97,
|
||||
};
|
||||
|
||||
/*------------------------- I2S PART ---------------------------*/
|
||||
|
@ -49,8 +44,8 @@ static struct snd_soc_device db1200_ac97_devdata = {
|
|||
static int db1200_i2s_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int ret;
|
||||
|
||||
/* WM8731 has its own 12MHz crystal */
|
||||
|
@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = {
|
|||
static struct snd_soc_dai_link db1200_i2s_dai = {
|
||||
.name = "WM8731",
|
||||
.stream_name = "WM8731 PCM",
|
||||
.cpu_dai = &au1xpsc_i2s_dai,
|
||||
.codec_dai = &wm8731_dai,
|
||||
.cpu_dai_name = "au1xpsc",
|
||||
.codec_dai_name = "wm8731-hifi"
|
||||
.platform_name = "au1xpsc-pcm-audio",
|
||||
.codec_name = "wm8731-codec.0-001a",
|
||||
.ops = &db1200_i2s_wm8731_ops,
|
||||
};
|
||||
|
||||
|
@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = {
|
|||
.name = "DB1200_I2S",
|
||||
.dai_link = &db1200_i2s_dai,
|
||||
.num_links = 1,
|
||||
.platform = &au1xpsc_soc_platform,
|
||||
};
|
||||
|
||||
static struct snd_soc_device db1200_i2s_devdata = {
|
||||
.card = &db1200_i2s_machine,
|
||||
.codec_dev = &soc_codec_dev_wm8731,
|
||||
};
|
||||
|
||||
/*------------------------- COMMON PART ---------------------------*/
|
||||
|
@ -112,12 +103,10 @@ static int __init db1200_audio_load(void)
|
|||
|
||||
/* DB1200 board setup set PSC1MUX to preferred audio device */
|
||||
if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
|
||||
platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata);
|
||||
platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
|
||||
else
|
||||
platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata);
|
||||
platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
|
||||
|
||||
db1200_ac97_devdata.dev = &db1200_asoc_dev->dev;
|
||||
db1200_i2s_devdata.dev = &db1200_asoc_dev->dev;
|
||||
ret = platform_device_add(db1200_asoc_dev);
|
||||
|
||||
if (ret) {
|
||||
|
|
|
@ -329,7 +329,7 @@ static int au1xpsc_pcm_new(struct snd_card *card,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int au1xpsc_pcm_probe(struct platform_device *pdev)
|
||||
static int au1xpsc_pcm_probe(struct snd_soc_platform *platform)
|
||||
{
|
||||
if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
|
||||
return -ENODEV;
|
||||
|
@ -337,17 +337,10 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int au1xpsc_pcm_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* au1xpsc audio platform */
|
||||
struct snd_soc_platform au1xpsc_soc_platform = {
|
||||
.name = "au1xpsc-pcm-dbdma",
|
||||
struct snd_soc_platform_driver au1xpsc_soc_platform = {
|
||||
.probe = au1xpsc_pcm_probe,
|
||||
.remove = au1xpsc_pcm_remove,
|
||||
.pcm_ops = &au1xpsc_pcm_ops,
|
||||
.ops = &au1xpsc_pcm_ops,
|
||||
.pcm_new = au1xpsc_pcm_new,
|
||||
.pcm_free = au1xpsc_pcm_free_dma_buffers,
|
||||
};
|
||||
|
@ -387,7 +380,7 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
|
|||
}
|
||||
(au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
|
||||
|
||||
ret = snd_soc_register_platform(&au1xpsc_soc_platform);
|
||||
ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
|
@ -404,7 +397,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
|
|||
{
|
||||
int i;
|
||||
|
||||
snd_soc_unregister_platform(&au1xpsc_soc_platform);
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (au1xpsc_audio_pcmdma[i]) {
|
||||
|
@ -419,7 +412,7 @@ static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
|
|||
|
||||
static struct platform_driver au1xpsc_pcm_driver = {
|
||||
.driver = {
|
||||
.name = "au1xpsc-pcm",
|
||||
.name = "au1xpsc-pcm-audio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = au1xpsc_pcm_drvprobe,
|
||||
|
|
|
@ -315,27 +315,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int au1xpsc_ac97_probe(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
return au1xpsc_ac97_workdata ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static void au1xpsc_ac97_remove(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
|
||||
.trigger = au1xpsc_ac97_trigger,
|
||||
.hw_params = au1xpsc_ac97_hw_params,
|
||||
};
|
||||
|
||||
struct snd_soc_dai au1xpsc_ac97_dai = {
|
||||
.name = "au1xpsc_ac97",
|
||||
struct snd_soc_dai_driver au1xpsc_ac97_dai = {
|
||||
.ac97_control = 1,
|
||||
.probe = au1xpsc_ac97_probe,
|
||||
.remove = au1xpsc_ac97_remove,
|
||||
.playback = {
|
||||
.rates = AC97_RATES,
|
||||
.formats = AC97_FMTS,
|
||||
|
@ -395,7 +387,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
|||
au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
|
||||
au_sync();
|
||||
|
||||
ret = snd_soc_register_dai(&au1xpsc_ac97_dai);
|
||||
ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai);
|
||||
if (ret)
|
||||
goto out1;
|
||||
|
||||
|
@ -406,7 +398,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
snd_soc_unregister_dai(&au1xpsc_ac97_dai);
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
out0:
|
||||
|
@ -422,7 +414,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
|
|||
if (wd->dmapd)
|
||||
au1xpsc_pcm_destroy(wd->dmapd);
|
||||
|
||||
snd_soc_unregister_dai(&au1xpsc_ac97_dai);
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
|
||||
/* disable PSC completely */
|
||||
au_writel(0, AC97_CFG(wd));
|
||||
|
@ -485,7 +477,7 @@ static struct dev_pm_ops au1xpscac97_pmops = {
|
|||
|
||||
static struct platform_driver au1xpsc_ac97_driver = {
|
||||
.driver = {
|
||||
.name = "au1xpsc_ac97",
|
||||
.name = "au1xpsc-ac97",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = AU1XPSCAC97_PMOPS,
|
||||
},
|
||||
|
|
|
@ -263,27 +263,19 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int au1xpsc_i2s_probe(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int au1xpsc_i2s_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
return au1xpsc_i2s_workdata ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static void au1xpsc_i2s_remove(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
|
||||
.trigger = au1xpsc_i2s_trigger,
|
||||
.hw_params = au1xpsc_i2s_hw_params,
|
||||
.set_fmt = au1xpsc_i2s_set_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai au1xpsc_i2s_dai = {
|
||||
.name = "au1xpsc_i2s",
|
||||
static struct snd_soc_dai_driver au1xpsc_i2s_dai = {
|
||||
.probe = au1xpsc_i2s_probe,
|
||||
.remove = au1xpsc_i2s_remove,
|
||||
.playback = {
|
||||
.rates = AU1XPSC_I2S_RATES,
|
||||
.formats = AU1XPSC_I2S_FMTS,
|
||||
|
@ -298,7 +290,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
|
|||
},
|
||||
.ops = &au1xpsc_i2s_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL(au1xpsc_i2s_dai);
|
||||
|
||||
static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -346,7 +337,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
|||
* time out.
|
||||
*/
|
||||
|
||||
ret = snd_soc_register_dai(&au1xpsc_i2s_dai);
|
||||
ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai);
|
||||
if (ret)
|
||||
goto out1;
|
||||
|
||||
|
@ -358,7 +349,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
snd_soc_unregister_dai(&au1xpsc_i2s_dai);
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
out1:
|
||||
release_mem_region(r->start, resource_size(r));
|
||||
out0:
|
||||
|
@ -374,7 +365,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
|
|||
if (wd->dmapd)
|
||||
au1xpsc_pcm_destroy(wd->dmapd);
|
||||
|
||||
snd_soc_unregister_dai(&au1xpsc_i2s_dai);
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
|
||||
au_writel(0, I2S_CFG(wd));
|
||||
au_sync();
|
||||
|
@ -436,7 +427,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = {
|
|||
|
||||
static struct platform_driver au1xpsc_i2s_driver = {
|
||||
.driver = {
|
||||
.name = "au1xpsc_i2s",
|
||||
.name = "au1xpsc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = AU1XPSCI2S_PMOPS,
|
||||
},
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
#ifndef _AU1X_PCM_H
|
||||
#define _AU1X_PCM_H
|
||||
|
||||
extern struct snd_soc_dai au1xpsc_ac97_dai;
|
||||
extern struct snd_soc_dai au1xpsc_i2s_dai;
|
||||
extern struct snd_soc_platform au1xpsc_soc_platform;
|
||||
extern struct snd_ac97_bus_ops soc_ac97_ops;
|
||||
|
||||
/* DBDMA helpers */
|
||||
|
|
|
@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
|
|||
if (!card->dev->coherent_dma_mask)
|
||||
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
if (dai->playback.channels_min) {
|
||||
if (dai->driver->playback.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dai->capture.channels_min) {
|
||||
if (dai->driver->capture.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
if (ret)
|
||||
|
@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct snd_soc_platform bf5xx_ac97_soc_platform = {
|
||||
.name = "bf5xx-audio",
|
||||
.pcm_ops = &bf5xx_pcm_ac97_ops,
|
||||
static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
|
||||
.ops = &bf5xx_pcm_ac97_ops,
|
||||
.pcm_new = bf5xx_pcm_ac97_new,
|
||||
.pcm_free = bf5xx_pcm_free_dma_buffers,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
|
||||
|
||||
static int __init bfin_ac97_init(void)
|
||||
static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
|
||||
return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
|
||||
}
|
||||
module_init(bfin_ac97_init);
|
||||
|
||||
static void __exit bfin_ac97_exit(void)
|
||||
static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
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_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
|
||||
|
|
|
@ -23,7 +23,4 @@ struct bf5xx_gpio {
|
|||
u32 frm;
|
||||
};
|
||||
|
||||
/* platform data */
|
||||
extern struct snd_soc_platform bf5xx_ac97_soc_platform;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
|
|||
#ifdef CONFIG_PM
|
||||
static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sport_device *sport = dai->private_data;
|
||||
struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
pr_debug("%s : sport %d\n", __func__, dai->id);
|
||||
if (!dai->active)
|
||||
|
@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
|
|||
static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret;
|
||||
struct sport_device *sport = dai->private_data;
|
||||
struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
pr_debug("%s : sport %d\n", __func__, dai->id);
|
||||
if (!dai->active)
|
||||
|
@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
|
|||
#define bf5xx_ac97_resume NULL
|
||||
#endif
|
||||
|
||||
static int bf5xx_ac97_probe(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret = 0;
|
||||
cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
|
||||
|
@ -379,8 +378,7 @@ peripheral_err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void bf5xx_ac97_remove(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
|
||||
{
|
||||
free_page((unsigned long)cmd_count);
|
||||
cmd_count = NULL;
|
||||
|
@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
|
|||
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
|
||||
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_dai bfin_ac97_dai = {
|
||||
.name = "bf5xx-ac97",
|
||||
.id = 0,
|
||||
struct snd_soc_dai_driver bfin_ac97_dai = {
|
||||
.ac97_control = 1,
|
||||
.probe = bf5xx_ac97_probe,
|
||||
.remove = bf5xx_ac97_remove,
|
||||
|
@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(bfin_ac97_dai);
|
||||
|
||||
static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
|
||||
}
|
||||
|
||||
static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver asoc_bfin_ac97_driver = {
|
||||
.driver = {
|
||||
.name = "bfin-ac97",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = asoc_bfin_ac97_probe,
|
||||
.remove = __devexit_p(asoc_bfin_ac97_remove),
|
||||
};
|
||||
|
||||
static int __init bfin_ac97_init(void)
|
||||
{
|
||||
return snd_soc_register_dai(&bfin_ac97_dai);
|
||||
return platform_driver_register(&asoc_bfin_ac97_driver);
|
||||
}
|
||||
module_init(bfin_ac97_init);
|
||||
|
||||
static void __exit bfin_ac97_exit(void)
|
||||
{
|
||||
snd_soc_unregister_dai(&bfin_ac97_dai);
|
||||
platform_driver_unregister(&asoc_bfin_ac97_driver);
|
||||
}
|
||||
module_exit(bfin_ac97_exit);
|
||||
|
||||
|
||||
MODULE_AUTHOR("Roy Huang");
|
||||
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -50,8 +50,6 @@ struct ac97_frame {
|
|||
#define TAG_PCM_SR 0x0080
|
||||
#define TAG_PCM_LFE 0x0040
|
||||
|
||||
extern struct snd_soc_dai bfin_ac97_dai;
|
||||
|
||||
void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
|
||||
size_t count, unsigned int chan_mask);
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836;
|
|||
static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
|
||||
cpu_dai->private_data = sport_handle;
|
||||
snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
|
||||
int ret = 0;
|
||||
/* set cpu DAI configuration */
|
||||
|
@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
|
|||
static struct snd_soc_dai_link bf5xx_ad1836_dai = {
|
||||
.name = "ad1836",
|
||||
.stream_name = "AD1836",
|
||||
.cpu_dai = &bf5xx_tdm_dai,
|
||||
.codec_dai = &ad1836_dai,
|
||||
.cpu_dai_name = "bf5xx-tdm",
|
||||
.codec_dai_name = "ad1836-hifi",
|
||||
.platform_name = "bf5xx-tdm-pcm-audio",
|
||||
.codec_name = "ad1836-codec.0",
|
||||
.ops = &bf5xx_ad1836_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card bf5xx_ad1836 = {
|
||||
.name = "bf5xx_ad1836",
|
||||
.platform = &bf5xx_tdm_soc_platform,
|
||||
.dai_link = &bf5xx_ad1836_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_device bf5xx_ad1836_snd_devdata = {
|
||||
.card = &bf5xx_ad1836,
|
||||
.codec_dev = &soc_codec_dev_ad1836,
|
||||
};
|
||||
|
||||
static struct platform_device *bfxx_ad1836_snd_device;
|
||||
|
||||
static int __init bf5xx_ad1836_init(void)
|
||||
|
@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void)
|
|||
if (!bfxx_ad1836_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata);
|
||||
bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev;
|
||||
platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836);
|
||||
ret = platform_device_add(bfxx_ad1836_snd_device);
|
||||
|
||||
if (ret)
|
||||
|
|
|
@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x;
|
|||
static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
|
||||
cpu_dai->private_data = sport_handle;
|
||||
snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
int ret = 0;
|
||||
/* set cpu DAI configuration */
|
||||
|
@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = {
|
|||
static struct snd_soc_dai_link bf5xx_ad193x_dai = {
|
||||
.name = "ad193x",
|
||||
.stream_name = "AD193X",
|
||||
.cpu_dai = &bf5xx_tdm_dai,
|
||||
.codec_dai = &ad193x_dai,
|
||||
.cpu_dai_name = "bf5xx-tdm",
|
||||
.codec_dai_name ="ad193x-hifi",
|
||||
.platform_name = "bf5xx-tdm-pcm-audio",
|
||||
.codec_name = "ad193x-codec.5",
|
||||
.ops = &bf5xx_ad193x_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card bf5xx_ad193x = {
|
||||
.name = "bf5xx_ad193x",
|
||||
.platform = &bf5xx_tdm_soc_platform,
|
||||
.dai_link = &bf5xx_ad193x_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
|
||||
.card = &bf5xx_ad193x,
|
||||
.codec_dev = &soc_codec_dev_ad193x,
|
||||
};
|
||||
|
||||
static struct platform_device *bfxx_ad193x_snd_device;
|
||||
|
||||
static int __init bf5xx_ad193x_init(void)
|
||||
|
@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void)
|
|||
if (!bfxx_ad193x_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata);
|
||||
bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
|
||||
platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x);
|
||||
ret = platform_device_add(bfxx_ad193x_snd_device);
|
||||
|
||||
if (ret)
|
||||
|
|
|
@ -48,10 +48,10 @@ static struct snd_soc_card bf5xx_board;
|
|||
static int bf5xx_board_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
cpu_dai->private_data = sport_handle;
|
||||
snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -62,23 +62,19 @@ static struct snd_soc_ops bf5xx_board_ops = {
|
|||
static struct snd_soc_dai_link bf5xx_board_dai = {
|
||||
.name = "AC97",
|
||||
.stream_name = "AC97 HiFi",
|
||||
.cpu_dai = &bfin_ac97_dai,
|
||||
.codec_dai = &ad1980_dai,
|
||||
.cpu_dai_name = "bfin-ac97",
|
||||
.codec_dai_name = "ad1980-hifi",
|
||||
.platform_name = "bfin-pcm-audio",
|
||||
.codec_name = "ad1980-codec",
|
||||
.ops = &bf5xx_board_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card bf5xx_board = {
|
||||
.name = "bf5xx-board",
|
||||
.platform = &bf5xx_ac97_soc_platform,
|
||||
.dai_link = &bf5xx_board_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_device bf5xx_board_snd_devdata = {
|
||||
.card = &bf5xx_board,
|
||||
.codec_dev = &soc_codec_dev_ad1980,
|
||||
};
|
||||
|
||||
static struct platform_device *bf5xx_board_snd_device;
|
||||
|
||||
static int __init bf5xx_board_init(void)
|
||||
|
@ -89,8 +85,7 @@ static int __init bf5xx_board_init(void)
|
|||
if (!bf5xx_board_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata);
|
||||
bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev;
|
||||
platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board);
|
||||
ret = platform_device_add(bf5xx_board_snd_device);
|
||||
|
||||
if (ret)
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "../codecs/ad73311.h"
|
||||
#include "bf5xx-sport.h"
|
||||
#include "bf5xx-i2s-pcm.h"
|
||||
#include "bf5xx-i2s.h"
|
||||
|
||||
#if CONFIG_SND_BF5XX_SPORT_NUM == 0
|
||||
#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
|
||||
|
@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev)
|
|||
static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
cpu_dai->private_data = sport_handle;
|
||||
snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -161,7 +160,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
|
||||
|
@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = {
|
|||
static struct snd_soc_dai_link bf5xx_ad73311_dai = {
|
||||
.name = "ad73311",
|
||||
.stream_name = "AD73311",
|
||||
.cpu_dai = &bf5xx_i2s_dai,
|
||||
.codec_dai = &ad73311_dai,
|
||||
.cpu_dai_name = "bf5xx-i2s",
|
||||
.codec_dai_name = "ad73311-hifi",
|
||||
.platform_name = "bfin-pcm-audio",
|
||||
.codec_name = "ad73311-codec",
|
||||
.ops = &bf5xx_ad73311_ops,
|
||||
};
|
||||
|
||||
static struct snd_soc_card bf5xx_ad73311 = {
|
||||
.name = "bf5xx_ad73311",
|
||||
.platform = &bf5xx_i2s_soc_platform,
|
||||
.probe = bf5xx_probe,
|
||||
.dai_link = &bf5xx_ad73311_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
|
||||
.card = &bf5xx_ad73311,
|
||||
.codec_dev = &soc_codec_dev_ad73311,
|
||||
};
|
||||
|
||||
static struct platform_device *bf5xx_ad73311_snd_device;
|
||||
|
||||
static int __init bf5xx_ad73311_init(void)
|
||||
|
@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void)
|
|||
if (!bf5xx_ad73311_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
|
||||
bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
|
||||
platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311);
|
||||
ret = platform_device_add(bf5xx_ad73311_snd_device);
|
||||
|
||||
if (ret)
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include <asm/dma.h>
|
||||
|
||||
#include "bf5xx-i2s-pcm.h"
|
||||
#include "bf5xx-i2s.h"
|
||||
#include "bf5xx-sport.h"
|
||||
|
||||
static void bf5xx_dma_irq(void *data)
|
||||
|
@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
|
|||
if (!card->dev->coherent_dma_mask)
|
||||
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
if (dai->playback.channels_min) {
|
||||
if (dai->driver->playback.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dai->capture.channels_min) {
|
||||
if (dai->driver->capture.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
if (ret)
|
||||
|
@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct snd_soc_platform bf5xx_i2s_soc_platform = {
|
||||
.name = "bf5xx-audio",
|
||||
.pcm_ops = &bf5xx_pcm_i2s_ops,
|
||||
static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
|
||||
.ops = &bf5xx_pcm_i2s_ops,
|
||||
.pcm_new = bf5xx_pcm_i2s_new,
|
||||
.pcm_free = bf5xx_pcm_free_dma_buffers,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
|
||||
|
||||
static int __init bfin_i2s_init(void)
|
||||
static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
|
||||
return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
|
||||
}
|
||||
module_init(bfin_i2s_init);
|
||||
|
||||
static void __exit bfin_i2s_exit(void)
|
||||
static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
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_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
|
||||
|
|
|
@ -23,7 +23,4 @@ struct bf5xx_gpio {
|
|||
u32 frm;
|
||||
};
|
||||
|
||||
/* platform data */
|
||||
extern struct snd_soc_platform bf5xx_i2s_soc_platform;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include <linux/gpio.h>
|
||||
|
||||
#include "bf5xx-sport.h"
|
||||
#include "bf5xx-i2s.h"
|
||||
|
||||
struct bf5xx_i2s_port {
|
||||
u16 tcr1;
|
||||
|
@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
|
|||
bf5xx_i2s.configured = 0;
|
||||
}
|
||||
|
||||
static int bf5xx_i2s_probe(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
pr_debug("%s enter\n", __func__);
|
||||
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
|
||||
|
@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bf5xx_i2s_remove(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai)
|
||||
static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
|
||||
{
|
||||
pr_debug("%s enter\n", __func__);
|
||||
peripheral_free_list(&sport_req[sport_num][0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
|
|||
|
||||
pr_debug("%s : sport %d\n", __func__, dai->id);
|
||||
|
||||
if (dai->capture.active)
|
||||
if (dai->capture_active)
|
||||
sport_rx_stop(sport_handle);
|
||||
if (dai->playback.active)
|
||||
if (dai->playback_active)
|
||||
sport_tx_stop(sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
|
|||
.set_fmt = bf5xx_i2s_set_dai_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai bf5xx_i2s_dai = {
|
||||
.name = "bf5xx-i2s",
|
||||
.id = 0,
|
||||
static struct snd_soc_dai_driver bf5xx_i2s_dai = {
|
||||
.probe = bf5xx_i2s_probe,
|
||||
.remove = bf5xx_i2s_remove,
|
||||
.suspend = bf5xx_i2s_suspend,
|
||||
|
@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = {
|
|||
.formats = BF5XX_I2S_FORMATS,},
|
||||
.ops = &bf5xx_i2s_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
|
||||
|
||||
static int bfin_i2s_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
|
||||
}
|
||||
|
||||
static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver bfin_i2s_driver = {
|
||||
.probe = bfin_i2s_drv_probe,
|
||||
.remove = __devexit_p(bfin_i2s_drv_remove),
|
||||
|
||||
.driver = {
|
||||
.name = "bf5xx-i2s",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init bfin_i2s_init(void)
|
||||
{
|
||||
return snd_soc_register_dai(&bf5xx_i2s_dai);
|
||||
return platform_driver_register(&bfin_i2s_driver);
|
||||
}
|
||||
module_init(bfin_i2s_init);
|
||||
|
||||
static void __exit bfin_i2s_exit(void)
|
||||
{
|
||||
snd_soc_unregister_dai(&bf5xx_i2s_dai);
|
||||
platform_driver_unregister(&bfin_i2s_driver);
|
||||
}
|
||||
|
||||
module_init(bfin_i2s_init);
|
||||
module_exit(bfin_i2s_exit);
|
||||
|
||||
/* Module information */
|
||||
|
|
|
@ -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
|
|
@ -42,17 +42,16 @@
|
|||
#include "../codecs/ssm2602.h"
|
||||
#include "bf5xx-sport.h"
|
||||
#include "bf5xx-i2s-pcm.h"
|
||||
#include "bf5xx-i2s.h"
|
||||
|
||||
static struct snd_soc_card bf5xx_ssm2602;
|
||||
|
||||
static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
|
||||
pr_debug("%s enter\n", __func__);
|
||||
cpu_dai->private_data = sport_handle;
|
||||
snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,8 +59,8 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
unsigned int clk = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
|
|||
static struct snd_soc_dai_link bf5xx_ssm2602_dai = {
|
||||
.name = "ssm2602",
|
||||
.stream_name = "SSM2602",
|
||||
.cpu_dai = &bf5xx_i2s_dai,
|
||||
.codec_dai = &ssm2602_dai,
|
||||
.cpu_dai_name = "bf5xx-i2s",
|
||||
.codec_dai_name = "ssm2602-hifi",
|
||||
.platform_name = "bf5xx-pcm-audio",
|
||||
.codec_name = "ssm2602-codec.0-0x1b",
|
||||
.ops = &bf5xx_ssm2602_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* SSM2602 2 wire address is determined by CSB
|
||||
* state during powerup.
|
||||
* low = 0x1a
|
||||
* high = 0x1b
|
||||
*/
|
||||
|
||||
static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
|
||||
.i2c_bus = 0,
|
||||
.i2c_address = 0x1b,
|
||||
};
|
||||
|
||||
static struct snd_soc_card bf5xx_ssm2602 = {
|
||||
.name = "bf5xx_ssm2602",
|
||||
.platform = &bf5xx_i2s_soc_platform,
|
||||
.dai_link = &bf5xx_ssm2602_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
|
||||
.card = &bf5xx_ssm2602,
|
||||
.codec_dev = &soc_codec_dev_ssm2602,
|
||||
.codec_data = &bf5xx_ssm2602_setup,
|
||||
};
|
||||
|
||||
static struct platform_device *bf5xx_ssm2602_snd_device;
|
||||
|
||||
static int __init bf5xx_ssm2602_init(void)
|
||||
|
@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void)
|
|||
if (!bf5xx_ssm2602_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(bf5xx_ssm2602_snd_device,
|
||||
&bf5xx_ssm2602_snd_devdata);
|
||||
bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
|
||||
platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602);
|
||||
ret = platform_device_add(bf5xx_ssm2602_snd_device);
|
||||
|
||||
if (ret)
|
||||
|
|
|
@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
|
|||
if (!card->dev->coherent_dma_mask)
|
||||
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
if (dai->playback.channels_min) {
|
||||
if (dai->driver->playback.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dai->capture.channels_min) {
|
||||
if (dai->driver->capture.channels_min) {
|
||||
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
if (ret)
|
||||
|
@ -307,25 +307,44 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct snd_soc_platform bf5xx_tdm_soc_platform = {
|
||||
.name = "bf5xx-audio",
|
||||
.pcm_ops = &bf5xx_pcm_tdm_ops,
|
||||
static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
|
||||
.ops = &bf5xx_pcm_tdm_ops,
|
||||
.pcm_new = bf5xx_pcm_tdm_new,
|
||||
.pcm_free = bf5xx_pcm_free_dma_buffers,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
|
||||
|
||||
static int __init bfin_pcm_tdm_init(void)
|
||||
static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
|
||||
return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
|
||||
}
|
||||
module_init(bfin_pcm_tdm_init);
|
||||
|
||||
static void __exit bfin_pcm_tdm_exit(void)
|
||||
static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
|
||||
snd_soc_unregister_platform(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
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_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
|
||||
|
|
|
@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params {
|
|||
char *name; /* stream identifier */
|
||||
};
|
||||
|
||||
/* platform data */
|
||||
extern struct snd_soc_platform bf5xx_tdm_soc_platform;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
|
|||
|
||||
if (!dai->active)
|
||||
return 0;
|
||||
if (dai->capture.active)
|
||||
if (dai->capture_active)
|
||||
sport_rx_stop(sport);
|
||||
if (dai->playback.active)
|
||||
if (dai->playback_active)
|
||||
sport_tx_stop(sport);
|
||||
return 0;
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
|
|||
static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret;
|
||||
struct sport_device *sport = dai->private_data;
|
||||
struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
if (!dai->active)
|
||||
return 0;
|
||||
|
@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
|
|||
.set_channel_map = bf5xx_tdm_set_channel_map,
|
||||
};
|
||||
|
||||
struct snd_soc_dai bf5xx_tdm_dai = {
|
||||
.name = "bf5xx-tdm",
|
||||
.id = 0,
|
||||
static struct snd_soc_dai_driver bf5xx_tdm_dai = {
|
||||
.suspend = bf5xx_tdm_suspend,
|
||||
.resume = bf5xx_tdm_resume,
|
||||
.playback = {
|
||||
|
@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S32_LE,},
|
||||
.ops = &bf5xx_tdm_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
|
||||
|
||||
static int __devinit bfin_tdm_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
|
|||
goto sport_config_err;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&bf5xx_tdm_dai);
|
||||
ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
|
||||
if (ret) {
|
||||
pr_err("Failed to register DAI: %d\n", ret);
|
||||
goto sport_config_err;
|
||||
|
@ -337,7 +334,7 @@ sport_config_err:
|
|||
static int __devexit bfin_tdm_remove(struct platform_device *pdev)
|
||||
{
|
||||
peripheral_free_list(&sport_req[sport_num][0]);
|
||||
snd_soc_unregister_dai(&bf5xx_tdm_dai);
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,4 @@ struct bf5xx_tdm_port {
|
|||
int configured;
|
||||
};
|
||||
|
||||
extern struct snd_soc_dai bf5xx_tdm_dai;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <sound/ac97_codec.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
#include "ac97.h"
|
||||
|
||||
#define AC97_VERSION "0.6"
|
||||
|
||||
|
@ -30,8 +29,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
|
||||
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
|
||||
|
@ -46,8 +44,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = {
|
|||
.prepare = ac97_prepare,
|
||||
};
|
||||
|
||||
struct snd_soc_dai ac97_dai = {
|
||||
.name = "AC97 HiFi",
|
||||
static struct snd_soc_dai_driver ac97_dai = {
|
||||
.name = "ac97-hifi",
|
||||
.ac97_control = 1,
|
||||
.playback = {
|
||||
.stream_name = "AC97 Playback",
|
||||
|
@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = {
|
|||
.formats = SND_SOC_STD_AC97_FMTS,},
|
||||
.ops = &ac97_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ac97_dai);
|
||||
|
||||
static unsigned int ac97_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
|
@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ac97_soc_probe(struct platform_device *pdev)
|
||||
static int ac97_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_card *card = socdev->card;
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_ac97_bus *ac97_bus;
|
||||
struct snd_ac97_template ac97_template;
|
||||
int i;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
|
||||
|
||||
socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (!socdev->card->codec)
|
||||
return -ENOMEM;
|
||||
codec = socdev->card->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
codec->name = "AC97";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ac97_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->write = ac97_write;
|
||||
codec->read = ac97_read;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* add codec as bus device for standard ac97 */
|
||||
ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
|
||||
ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);
|
||||
if (ret < 0)
|
||||
goto bus_err;
|
||||
return ret;
|
||||
|
||||
memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
|
||||
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
|
||||
if (ret < 0)
|
||||
goto bus_err;
|
||||
|
||||
for (i = 0; i < card->num_links; i++) {
|
||||
if (card->dai_link[i].codec_dai->ac97_control) {
|
||||
snd_ac97_dev_add_pdata(codec->ac97,
|
||||
card->dai_link[i].cpu_dai->ac97_pdata);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bus_err:
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
err:
|
||||
kfree(socdev->card->codec);
|
||||
socdev->card->codec = NULL;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac97_soc_remove(struct platform_device *pdev)
|
||||
static int ac97_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
if (!codec)
|
||||
return 0;
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
kfree(socdev->card->codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg)
|
||||
static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_ac97_suspend(socdev->card->codec->ac97);
|
||||
snd_ac97_suspend(codec->ac97);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac97_soc_resume(struct platform_device *pdev)
|
||||
static int ac97_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_ac97_resume(socdev->card->codec->ac97);
|
||||
snd_ac97_resume(codec->ac97);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev)
|
|||
#define ac97_soc_resume NULL
|
||||
#endif
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ac97 = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
|
||||
.write = ac97_write,
|
||||
.read = ac97_read,
|
||||
.probe = ac97_soc_probe,
|
||||
.remove = ac97_soc_remove,
|
||||
.suspend = ac97_soc_suspend,
|
||||
.resume = ac97_soc_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
|
||||
|
||||
static __devinit int ac97_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_ac97, &ac97_dai, 1);
|
||||
}
|
||||
|
||||
static int __devexit ac97_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ac97_codec_driver = {
|
||||
.driver = {
|
||||
.name = "ac97-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = ac97_probe,
|
||||
.remove = __devexit_p(ac97_remove),
|
||||
};
|
||||
|
||||
static int __init ac97_init(void)
|
||||
{
|
||||
return platform_driver_register(&ac97_codec_driver);
|
||||
}
|
||||
module_init(ac97_init);
|
||||
|
||||
static void __exit ac97_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ac97_codec_driver);
|
||||
}
|
||||
module_exit(ac97_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Soc Generic AC97 driver");
|
||||
MODULE_AUTHOR("Liam Girdwood");
|
||||
|
|
|
@ -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
|
|
@ -33,15 +33,10 @@
|
|||
|
||||
/* codec private data */
|
||||
struct ad1836_priv {
|
||||
struct snd_soc_codec codec;
|
||||
u16 reg_cache[AD1836_NUM_REGS];
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
static struct snd_soc_codec *ad1836_codec;
|
||||
struct snd_soc_codec_device soc_codec_dev_ad1836;
|
||||
static int ad1836_register(struct ad1836_priv *ad1836);
|
||||
static void ad1836_unregister(struct ad1836_priv *ad1836);
|
||||
|
||||
/*
|
||||
* AD1836 volume/mute/de-emphasis etc. controls
|
||||
*/
|
||||
|
@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
|
|||
int word_len = 0;
|
||||
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
|
||||
/* bit size */
|
||||
switch (params_format(params)) {
|
||||
|
@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ad1836_soc_suspend(struct platform_device *pdev,
|
||||
static int ad1836_soc_suspend(struct snd_soc_codec *codec,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
/* reset clock control mode */
|
||||
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
|
||||
adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
|
||||
|
@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
|
|||
return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
|
||||
}
|
||||
|
||||
static int ad1836_soc_resume(struct platform_device *pdev)
|
||||
static int ad1836_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
/* restore clock control mode */
|
||||
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
|
||||
adc_ctrl2 |= AD1836_ADC_AUX;
|
||||
|
@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
|
|||
#define ad1836_soc_resume NULL
|
||||
#endif
|
||||
|
||||
static int __devinit ad1836_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct ad1836_priv *ad1836;
|
||||
|
||||
ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
|
||||
if (ad1836 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &ad1836->codec;
|
||||
codec->control_data = spi;
|
||||
codec->dev = &spi->dev;
|
||||
|
||||
dev_set_drvdata(&spi->dev, ad1836);
|
||||
|
||||
return ad1836_register(ad1836);
|
||||
}
|
||||
|
||||
static int __devexit ad1836_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
|
||||
|
||||
ad1836_unregister(ad1836);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ad1836_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ad1836",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad1836_spi_probe,
|
||||
.remove = __devexit_p(ad1836_spi_remove),
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_ops ad1836_dai_ops = {
|
||||
.hw_params = ad1836_hw_params,
|
||||
.set_fmt = ad1836_set_dai_fmt,
|
||||
};
|
||||
|
||||
/* codec DAI instance */
|
||||
struct snd_soc_dai ad1836_dai = {
|
||||
.name = "AD1836",
|
||||
static struct snd_soc_dai_driver ad1836_dai = {
|
||||
.name = "ad1836-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
|
@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
|
|||
},
|
||||
.ops = &ad1836_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ad1836_dai);
|
||||
|
||||
static int ad1836_register(struct ad1836_priv *ad1836)
|
||||
static int ad1836_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_codec *codec = &ad1836->codec;
|
||||
|
||||
if (ad1836_codec) {
|
||||
dev_err(codec->dev, "Another ad1836 is registered\n");
|
||||
kfree(ad1836);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
snd_soc_codec_set_drvdata(codec, ad1836);
|
||||
codec->reg_cache = ad1836->reg_cache;
|
||||
codec->reg_cache_size = AD1836_NUM_REGS;
|
||||
codec->name = "AD1836";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ad1836_dai;
|
||||
codec->num_dai = 1;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
ad1836_dai.dev = codec->dev;
|
||||
ad1836_codec = codec;
|
||||
struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret = 0;
|
||||
|
||||
codec->control_data = ad1836->control_data;
|
||||
ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n",
|
||||
|
@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
|
|||
snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
|
||||
snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
kfree(ad1836);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&ad1836_dai);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
|
||||
snd_soc_unregister_codec(codec);
|
||||
kfree(ad1836);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ad1836_unregister(struct ad1836_priv *ad1836)
|
||||
{
|
||||
snd_soc_unregister_dai(&ad1836_dai);
|
||||
snd_soc_unregister_codec(&ad1836->codec);
|
||||
kfree(ad1836);
|
||||
ad1836_codec = NULL;
|
||||
}
|
||||
|
||||
static int ad1836_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
|
||||
if (ad1836_codec == NULL) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
socdev->card->codec = ad1836_codec;
|
||||
codec = ad1836_codec;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, ad1836_snd_controls,
|
||||
ARRAY_SIZE(ad1836_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
|
||||
ARRAY_SIZE(ad1836_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
|
||||
pcm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int ad1836_remove(struct platform_device *pdev)
|
||||
static int ad1836_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
/* 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);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
return 0;
|
||||
return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ad1836 = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
|
||||
.probe = ad1836_probe,
|
||||
.remove = ad1836_remove,
|
||||
.suspend = ad1836_soc_suspend,
|
||||
.resume = ad1836_soc_resume,
|
||||
.reg_cache_size = AD1836_NUM_REGS,
|
||||
.reg_word_size = sizeof(u16),
|
||||
};
|
||||
|
||||
static int __devinit ad1836_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad1836_priv *ad1836;
|
||||
int ret;
|
||||
|
||||
ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
|
||||
if (ad1836 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, ad1836);
|
||||
ad1836->control_data = spi;
|
||||
ad1836->control_type = SND_SOC_SPI;
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_ad1836, &ad1836_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ad1836);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ad1836_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
kfree(spi_get_drvdata(spi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ad1836_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ad1836-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad1836_spi_probe,
|
||||
.remove = __devexit_p(ad1836_spi_remove),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
|
||||
|
||||
static int __init ad1836_init(void)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,4 @@
|
|||
|
||||
#define AD1836_NUM_REGS 16
|
||||
|
||||
extern struct snd_soc_dai ad1836_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ad1836;
|
||||
#endif
|
||||
|
|
|
@ -24,9 +24,10 @@
|
|||
|
||||
/* codec private data */
|
||||
struct ad193x_priv {
|
||||
unsigned int sysclk;
|
||||
struct snd_soc_codec codec;
|
||||
u8 reg_cache[AD193X_NUM_REGS];
|
||||
enum snd_soc_control_type bus_type;
|
||||
void *control_data;
|
||||
int sysclk;
|
||||
};
|
||||
|
||||
/* ad193x register cache & default register settings */
|
||||
|
@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = {
|
|||
0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec *ad193x_codec;
|
||||
struct snd_soc_codec_device soc_codec_dev_ad193x;
|
||||
|
||||
/*
|
||||
* AD193X volume/mute/de-emphasis etc. controls
|
||||
*/
|
||||
|
@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
|||
int word_len = 0, reg = 0, master_rate = 0;
|
||||
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* bit size */
|
||||
|
@ -323,46 +320,46 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
|
||||
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;
|
||||
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
if (ad193x_codec) {
|
||||
dev_err(dev, "Another ad193x is registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
|
||||
if (ad193x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, ad193x);
|
||||
|
||||
codec = &ad193x->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
codec->control_data = ctrl_data;
|
||||
codec->dev = dev;
|
||||
snd_soc_codec_set_drvdata(codec, ad193x);
|
||||
codec->reg_cache = ad193x->reg_cache;
|
||||
codec->reg_cache_size = AD193X_NUM_REGS;
|
||||
codec->name = "AD193X";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ad193x_dai;
|
||||
codec->num_dai = 1;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
ad193x_dai.dev = codec->dev;
|
||||
ad193x_codec = codec;
|
||||
|
||||
memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
|
||||
|
||||
if (bus_type == SND_SOC_I2C)
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
|
||||
codec->control_data = ad193x->control_data;
|
||||
if (ad193x->bus_type == SND_SOC_I2C)
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type);
|
||||
else
|
||||
ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to set cache I/O: %d\n",
|
||||
ret);
|
||||
|
@ -385,89 +382,6 @@ static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
|
|||
/* pll input: mclki/xi */
|
||||
snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
|
||||
snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
|
||||
ad193x->sysclk = 12288000;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
kfree(ad193x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&ad193x_dai);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
|
||||
snd_soc_unregister_codec(codec);
|
||||
kfree(ad193x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad193x_bus_remove(struct device *dev)
|
||||
{
|
||||
struct ad193x_priv *ad193x = dev_get_drvdata(dev);
|
||||
|
||||
snd_soc_unregister_dai(&ad193x_dai);
|
||||
snd_soc_unregister_codec(&ad193x->codec);
|
||||
kfree(ad193x);
|
||||
ad193x_codec = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops ad193x_dai_ops = {
|
||||
.hw_params = ad193x_hw_params,
|
||||
.digital_mute = ad193x_mute,
|
||||
.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,
|
||||
ARRAY_SIZE(ad193x_snd_controls));
|
||||
|
@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev)
|
|||
ARRAY_SIZE(ad193x_dapm_widgets));
|
||||
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
|
||||
|
||||
pcm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int ad193x_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ad193x = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
|
||||
.probe = ad193x_probe,
|
||||
.remove = ad193x_remove,
|
||||
.reg_cache_default = ad193x_reg,
|
||||
.reg_cache_size = AD193X_NUM_REGS,
|
||||
.reg_word_size = sizeof(u16),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
|
||||
|
||||
#if defined(CONFIG_SPI_MASTER)
|
||||
static int __devinit ad193x_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
|
||||
struct ad193x_priv *ad193x;
|
||||
int ret;
|
||||
|
||||
ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
|
||||
if (ad193x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, ad193x);
|
||||
ad193x->control_data = spi;
|
||||
ad193x->bus_type = SND_SOC_SPI;
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_ad193x, &ad193x_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ad193x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ad193x_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
return ad193x_bus_remove(&spi->dev);
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
kfree(spi_get_drvdata(spi));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver ad193x_spi_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
.name = "ad193x-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad193x_spi_probe,
|
||||
|
@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);
|
|||
static int __devinit ad193x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C);
|
||||
struct ad193x_priv *ad193x;
|
||||
int ret;
|
||||
|
||||
ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
|
||||
if (ad193x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, ad193x);
|
||||
ad193x->control_data = client;
|
||||
ad193x->bus_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
&soc_codec_dev_ad193x, &ad193x_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ad193x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ad193x_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
return ad193x_bus_remove(&client->dev);
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver ad193x_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ad193x",
|
||||
.name = "ad193x-codec",
|
||||
},
|
||||
.probe = ad193x_i2c_probe,
|
||||
.remove = __devexit_p(ad193x_i2c_remove),
|
||||
|
|
|
@ -80,7 +80,4 @@
|
|||
|
||||
#define AD193X_NUM_REGS 17
|
||||
|
||||
extern struct snd_soc_dai ad193x_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ad193x;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_dai ad1980_dai = {
|
||||
.name = "AC97",
|
||||
struct snd_soc_dai_driver ad1980_dai = {
|
||||
.name = "ad1980-hifi",
|
||||
.ac97_control = 1,
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
|
@ -177,53 +177,20 @@ err:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int ad1980_soc_probe(struct platform_device *pdev)
|
||||
static int ad1980_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
u16 vendor_id2;
|
||||
u16 ext_status;
|
||||
|
||||
printk(KERN_INFO "AD1980 SoC Audio Codec\n");
|
||||
|
||||
socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (socdev->card->codec == NULL)
|
||||
return -ENOMEM;
|
||||
codec = socdev->card->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
codec->reg_cache =
|
||||
kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
|
||||
if (codec->reg_cache == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto cache_err;
|
||||
}
|
||||
memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
|
||||
ARRAY_SIZE(ad1980_reg));
|
||||
codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
|
||||
codec->reg_cache_step = 2;
|
||||
codec->name = "AD1980";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ad1980_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->write = ac97_write;
|
||||
codec->read = ac97_read;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
|
||||
goto codec_err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0)
|
||||
goto pcm_err;
|
||||
|
||||
|
||||
ret = ad1980_reset(codec, 0);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
|
||||
|
@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
reset_err:
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
pcm_err:
|
||||
snd_soc_free_ac97_codec(codec);
|
||||
|
||||
codec_err:
|
||||
kfree(codec->reg_cache);
|
||||
|
||||
cache_err:
|
||||
kfree(socdev->card->codec);
|
||||
socdev->card->codec = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad1980_soc_remove(struct platform_device *pdev)
|
||||
static int ad1980_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
if (codec == NULL)
|
||||
return 0;
|
||||
|
||||
snd_soc_dapm_free(socdev);
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_free_ac97_codec(codec);
|
||||
kfree(codec->reg_cache);
|
||||
kfree(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ad1980 = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
|
||||
.probe = ad1980_soc_probe,
|
||||
.remove = ad1980_soc_remove,
|
||||
.reg_cache_size = ARRAY_SIZE(ad1980_reg),
|
||||
.reg_word_size = sizeof(u16),
|
||||
.reg_cache_step = 2,
|
||||
.write = ac97_write,
|
||||
.read = ac97_read,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980);
|
||||
|
||||
static __devinit int ad1980_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_ad1980, &ad1980_dai, 1);
|
||||
}
|
||||
|
||||
static int __devexit ad1980_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ad1980_codec_driver = {
|
||||
.driver = {
|
||||
.name = "ad1980-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = ad1980_probe,
|
||||
.remove = __devexit_p(ad1980_remove),
|
||||
};
|
||||
|
||||
static int __init ad1980_init(void)
|
||||
{
|
||||
return platform_driver_register(&ad1980_codec_driver);
|
||||
}
|
||||
module_init(ad1980_init);
|
||||
|
||||
static void __exit ad1980_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ad1980_codec_driver);
|
||||
}
|
||||
module_exit(ad1980_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC ad1980 driver");
|
||||
MODULE_AUTHOR("Roy Huang, Cliff Cai");
|
||||
|
|
|
@ -17,7 +17,4 @@
|
|||
#define PR5 0x2000
|
||||
#define PR6 0x4000
|
||||
|
||||
extern struct snd_soc_dai ad1980_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ad1980;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
#include "ad73311.h"
|
||||
|
||||
struct snd_soc_dai ad73311_dai = {
|
||||
.name = "AD73311",
|
||||
static struct snd_soc_dai_driver ad73311_dai = {
|
||||
.name = "ad73311-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {
|
|||
.rates = SNDRV_PCM_RATE_8000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ad73311_dai);
|
||||
|
||||
static int ad73311_soc_probe(struct platform_device *pdev)
|
||||
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);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
mutex_init(&codec->mutex);
|
||||
codec->name = "AD73311";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ad73311_dai;
|
||||
codec->num_dai = 1;
|
||||
socdev->card->codec = codec;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "ad73311: failed to create pcms\n");
|
||||
goto pcm_err;
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_ad73311, &ad73311_dai, 1);
|
||||
}
|
||||
|
||||
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);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
if (codec == NULL)
|
||||
return 0;
|
||||
snd_soc_free_pcms(socdev);
|
||||
kfree(codec);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ad73311 = {
|
||||
.probe = ad73311_soc_probe,
|
||||
.remove = ad73311_soc_remove,
|
||||
static struct platform_driver ad73311_codec_driver = {
|
||||
.driver = {
|
||||
.name = "ad73311-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = ad73311_probe,
|
||||
.remove = __devexit_p(ad73311_remove),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
|
||||
|
||||
static int __init ad73311_init(void)
|
||||
{
|
||||
return snd_soc_register_dai(&ad73311_dai);
|
||||
return platform_driver_register(&ad73311_codec_driver);
|
||||
}
|
||||
module_init(ad73311_init);
|
||||
|
||||
static void __exit ad73311_exit(void)
|
||||
{
|
||||
snd_soc_unregister_dai(&ad73311_dai);
|
||||
platform_driver_unregister(&ad73311_codec_driver);
|
||||
}
|
||||
module_exit(ad73311_exit);
|
||||
|
||||
|
|
|
@ -85,6 +85,4 @@
|
|||
#define REGF_INV (1 << 6)
|
||||
#define REGF_ALB (1 << 7)
|
||||
|
||||
extern struct snd_soc_dai ad73311_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ad73311;
|
||||
#endif
|
||||
|
|
|
@ -19,16 +19,12 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "ads117x.h"
|
||||
|
||||
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
|
||||
|
||||
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
|
||||
|
||||
struct snd_soc_dai ads117x_dai = {
|
||||
static struct snd_soc_dai_driver ads117x_dai = {
|
||||
/* ADC */
|
||||
.name = "ADS117X ADC",
|
||||
.id = 1,
|
||||
.name = "ads117x-hifi",
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
|
@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {
|
|||
.rates = ADS117X_RATES,
|
||||
.formats = ADS117X_FORMATS,},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ads117x_dai);
|
||||
|
||||
static int ads117x_probe(struct platform_device *pdev)
|
||||
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);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
socdev->card->codec = codec;
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
codec->name = "ADS117X";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &ads117x_dai;
|
||||
codec->num_dai = 1;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "ads117x: failed to create pcms\n");
|
||||
kfree(codec);
|
||||
return ret;
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_ads117x, &ads117x_dai, 1);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ads117x_codec_driver = {
|
||||
.driver = {
|
||||
.name = "ads117x",
|
||||
.name = "ads117x-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = ads117x_platform_probe,
|
||||
.remove = __devexit_p(ads117x_platform_remove),
|
||||
.probe = ads117x_probe,
|
||||
.remove = __devexit_p(ads117x_remove),
|
||||
};
|
||||
|
||||
static int __init ads117x_init(void)
|
||||
|
|
|
@ -9,5 +9,5 @@
|
|||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
extern struct snd_soc_dai ads117x_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ads117x;
|
||||
extern struct snd_soc_dai_driver ads117x_dai;
|
||||
extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include <linux/spi/spi.h>
|
||||
#include <sound/asoundef.h>
|
||||
|
||||
#include "ak4104.h"
|
||||
|
||||
/* AK4104 registers addresses */
|
||||
#define AK4104_REG_CONTROL1 0x00
|
||||
#define AK4104_REG_RESERVED 0x01
|
||||
|
@ -45,11 +43,11 @@
|
|||
#define AK4104_TX_TXE (1 << 0)
|
||||
#define AK4104_TX_V (1 << 1)
|
||||
|
||||
#define DRV_NAME "ak4104"
|
||||
#define DRV_NAME "ak4104-codec"
|
||||
|
||||
struct ak4104_private {
|
||||
struct snd_soc_codec codec;
|
||||
u8 reg_cache[AK4104_NUM_REGS];
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
static int ak4104_fill_cache(struct snd_soc_codec *codec)
|
||||
|
@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec)
|
|||
u8 *reg_cache = codec->reg_cache;
|
||||
struct spi_device *spi = codec->control_data;
|
||||
|
||||
for (i = 0; i < codec->reg_cache_size; i++) {
|
||||
for (i = 0; i < codec->driver->reg_cache_size; i++) {
|
||||
int ret = spi_w8r8(spi, i | AK4104_READ);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "SPI write failure\n");
|
||||
|
@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
|
|||
{
|
||||
u8 *reg_cache = codec->reg_cache;
|
||||
|
||||
if (reg >= codec->reg_cache_size)
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EINVAL;
|
||||
|
||||
return reg_cache[reg];
|
||||
|
@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
u8 *cache = codec->reg_cache;
|
||||
struct spi_device *spi = codec->control_data;
|
||||
|
||||
if (reg >= codec->reg_cache_size)
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EINVAL;
|
||||
|
||||
/* only write to the hardware if value has changed */
|
||||
|
@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
int val = 0;
|
||||
|
||||
/* set the IEC958 bits: consumer mode, no copyright bit */
|
||||
|
@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = {
|
|||
.set_fmt = ak4104_set_dai_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai ak4104_dai = {
|
||||
.name = DRV_NAME,
|
||||
static struct snd_soc_dai_driver ak4104_dai = {
|
||||
.name = "ak4104-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
|
@ -192,13 +189,71 @@ struct snd_soc_dai ak4104_dai = {
|
|||
.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)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct ak4104_private *ak4104;
|
||||
int ret, val;
|
||||
int ret;
|
||||
|
||||
spi->bits_per_word = 8;
|
||||
spi->mode = SPI_MODE_0;
|
||||
|
@ -207,125 +262,27 @@ static int ak4104_spi_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
|
||||
ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
|
||||
if (!ak4104) {
|
||||
dev_err(&spi->dev, "could not allocate codec\n");
|
||||
if (ak4104 == NULL)
|
||||
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);
|
||||
dev_info(&spi->dev, "SPI device initialized\n");
|
||||
return 0;
|
||||
|
||||
error_free_codec:
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_device_ak4104, &ak4104_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ak4104);
|
||||
ak4104_dai.dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ak4104_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
int ret, val;
|
||||
struct ak4104_private *ak4104 = spi_get_drvdata(spi);
|
||||
|
||||
val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
/* clear power-up and non-reset bits */
|
||||
val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
|
||||
ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ak4104_codec = NULL;
|
||||
kfree(ak4104);
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
kfree(spi_get_drvdata(spi));
|
||||
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 = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
|
|
@ -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
|
|
@ -31,11 +31,11 @@
|
|||
|
||||
#define AK4535_VERSION "0.3"
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ak4535;
|
||||
|
||||
/* codec private data */
|
||||
struct ak4535_priv {
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
|
||||
int rate = params_rate(params), fs = 256;
|
||||
|
@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute)
|
|||
static int ak4535_set_bias_level(struct snd_soc_codec *codec,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
u16 i;
|
||||
u16 i, mute_reg;
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
ak4535_mute(codec->dai, 0);
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg);
|
||||
break;
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
ak4535_mute(codec->dai, 1);
|
||||
mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
|
||||
ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
|
||||
break;
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
i = ak4535_read_reg_cache(codec, AK4535_PM1);
|
||||
|
@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = {
|
|||
.set_sysclk = ak4535_set_dai_sysclk,
|
||||
};
|
||||
|
||||
struct snd_soc_dai ak4535_dai = {
|
||||
.name = "AK4535",
|
||||
static struct snd_soc_dai_driver ak4535_dai = {
|
||||
.name = "ak4535-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
|
||||
.ops = &ak4535_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ak4535_dai);
|
||||
|
||||
static int ak4535_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ak4535_resume(struct platform_device *pdev)
|
||||
static int ak4535_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
ak4535_sync(codec);
|
||||
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the AK4535 driver
|
||||
* register the mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int ak4535_init(struct snd_soc_device *socdev)
|
||||
static int ak4535_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
int ret = 0;
|
||||
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
codec->name = "AK4535";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = ak4535_read_reg_cache;
|
||||
codec->write = ak4535_write;
|
||||
codec->set_bias_level = ak4535_set_bias_level;
|
||||
codec->dai = &ak4535_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
|
||||
codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
|
||||
printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
|
||||
|
||||
if (codec->reg_cache == NULL)
|
||||
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;
|
||||
}
|
||||
codec->control_data = ak4535->control_data;
|
||||
|
||||
/* power on device */
|
||||
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev)
|
|||
ARRAY_SIZE(ak4535_snd_controls));
|
||||
ak4535_add_widgets(codec);
|
||||
|
||||
return ret;
|
||||
|
||||
pcm_err:
|
||||
kfree(codec->reg_cache);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
static int ak4535_i2c_probe(struct i2c_client *i2c,
|
||||
static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct snd_soc_device *socdev = ak4535_socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct ak4535_priv *ak4535;
|
||||
int ret;
|
||||
|
||||
i2c_set_clientdata(i2c, codec);
|
||||
codec->control_data = i2c;
|
||||
ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
|
||||
if (ak4535 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ak4535_init(socdev);
|
||||
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)
|
||||
printk(KERN_ERR "failed to initialise AK4535\n");
|
||||
|
||||
kfree(ak4535);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ak4535_i2c_remove(struct i2c_client *client)
|
||||
static __devexit int ak4535_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct snd_soc_codec *codec = i2c_get_clientdata(client);
|
||||
kfree(codec->reg_cache);
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
|
|||
|
||||
static struct i2c_driver ak4535_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "AK4535 I2C Codec",
|
||||
.name = "ak4535-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ak4535_i2c_probe,
|
||||
.remove = ak4535_i2c_remove,
|
||||
.remove = __devexit_p(ak4535_i2c_remove),
|
||||
.id_table = ak4535_i2c_id,
|
||||
};
|
||||
|
||||
static int ak4535_add_i2c_device(struct platform_device *pdev,
|
||||
const struct ak4535_setup_data *setup)
|
||||
{
|
||||
struct i2c_board_info info;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *client;
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&ak4535_i2c_driver);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "can't add i2c driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
info.addr = setup->i2c_address;
|
||||
strlcpy(info.type, "ak4535", I2C_NAME_SIZE);
|
||||
|
||||
adapter = i2c_get_adapter(setup->i2c_bus);
|
||||
if (!adapter) {
|
||||
dev_err(&pdev->dev, "can't get i2c adapter %d\n",
|
||||
setup->i2c_bus);
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
client = i2c_new_device(adapter, &info);
|
||||
i2c_put_adapter(adapter);
|
||||
if (!client) {
|
||||
dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
|
||||
(unsigned int)info.addr);
|
||||
goto err_driver;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_driver:
|
||||
i2c_del_driver(&ak4535_i2c_driver);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ak4535_probe(struct platform_device *pdev)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -36,12 +36,4 @@
|
|||
|
||||
#define AK4535_CACHEREGNUM 0x10
|
||||
|
||||
struct ak4535_setup_data {
|
||||
int i2c_bus;
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
extern struct snd_soc_dai ak4535_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ak4535;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "ak4642.h"
|
||||
|
||||
#define AK4642_VERSION "0.0.1"
|
||||
|
||||
#define PW_MGMT1 0x00
|
||||
|
@ -102,7 +100,6 @@
|
|||
#define FS3 (1 << 5)
|
||||
#define FS_MASK (FS0 | FS1 | FS2 | FS3)
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ak4642;
|
||||
|
||||
/*
|
||||
* Playback Volume (table 39)
|
||||
|
@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
|
|||
|
||||
/* codec private data */
|
||||
struct ak4642_priv {
|
||||
struct snd_soc_codec codec;
|
||||
unsigned int sysclk;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
static struct snd_soc_codec *ak4642_codec;
|
||||
|
||||
/*
|
||||
* ak4642 register cache
|
||||
*/
|
||||
|
@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
|
|||
.hw_params = ak4642_dai_hw_params,
|
||||
};
|
||||
|
||||
struct snd_soc_dai ak4642_dai = {
|
||||
.name = "AK4642",
|
||||
static struct snd_soc_dai_driver ak4642_dai = {
|
||||
.name = "ak4642-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = {
|
|||
.ops = &ak4642_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ak4642_dai);
|
||||
|
||||
static int ak4642_resume(struct platform_device *pdev)
|
||||
static int ak4642_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
ak4642_sync(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the AK4642 driver
|
||||
* register the mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int ak4642_init(struct ak4642_priv *ak4642)
|
||||
|
||||
static int ak4642_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_codec *codec = &ak4642->codec;
|
||||
int ret = 0;
|
||||
struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (ak4642_codec) {
|
||||
dev_err(codec->dev, "Another ak4642 is registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, ak4642);
|
||||
codec->name = "AK4642";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = ak4642_read_reg_cache;
|
||||
codec->write = ak4642_write;
|
||||
codec->dai = &ak4642_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
codec->reg_cache_size = ARRAY_SIZE(ak4642_reg);
|
||||
codec->reg_cache = kmemdup(ak4642_reg,
|
||||
sizeof(ak4642_reg), GFP_KERNEL);
|
||||
codec->control_data = ak4642->control_data;
|
||||
|
||||
if (!codec->reg_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
ak4642_dai.dev = codec->dev;
|
||||
ak4642_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto reg_cache_err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
struct ak4642_priv *ak4642;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
|
||||
if (!ak4642)
|
||||
if (ak4642 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &ak4642->codec;
|
||||
codec->dev = &i2c->dev;
|
||||
|
||||
i2c_set_clientdata(i2c, ak4642);
|
||||
codec->control_data = i2c;
|
||||
ak4642->control_data = i2c;
|
||||
ak4642->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = ak4642_init(ak4642);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "failed to initialise AK4642\n");
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_ak4642, &ak4642_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ak4642);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ak4642_i2c_remove(struct i2c_client *client)
|
||||
static __devexit int ak4642_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ak4642_priv *ak4642 = i2c_get_clientdata(client);
|
||||
|
||||
snd_soc_unregister_dai(&ak4642_dai);
|
||||
snd_soc_unregister_codec(&ak4642->codec);
|
||||
kfree(ak4642->codec.reg_cache);
|
||||
kfree(ak4642);
|
||||
ak4642_codec = NULL;
|
||||
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
|
|||
|
||||
static struct i2c_driver ak4642_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "AK4642 I2C Codec",
|
||||
.name = "ak4642-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ak4642_i2c_probe,
|
||||
.remove = ak4642_i2c_remove,
|
||||
.remove = __devexit_p(ak4642_i2c_remove),
|
||||
.id_table = ak4642_i2c_id,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int ak4642_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (!ak4642_codec) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
socdev->card->codec = ak4642_codec;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "ak4642: failed to create pcms\n");
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
|
||||
ARRAY_SIZE(ak4642_snd_controls));
|
||||
|
||||
dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
|
||||
return ret;
|
||||
|
||||
pcm_err:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* power down chip */
|
||||
static int ak4642_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ak4642 = {
|
||||
.probe = ak4642_probe,
|
||||
.remove = ak4642_remove,
|
||||
.resume = ak4642_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
|
||||
|
||||
static int __init ak4642_modinit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
@ -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
|
|
@ -23,11 +23,11 @@
|
|||
|
||||
#include "ak4671.h"
|
||||
|
||||
static struct snd_soc_codec *ak4671_codec;
|
||||
|
||||
/* codec private data */
|
||||
struct ak4671_priv {
|
||||
struct snd_soc_codec codec;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[AK4671_CACHEREGNUM];
|
||||
};
|
||||
|
||||
|
@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
|
|||
.set_fmt = ak4671_set_dai_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai ak4671_dai = {
|
||||
.name = "AK4671",
|
||||
static struct snd_soc_dai_driver ak4671_dai = {
|
||||
.name = "ak4671-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = {
|
|||
.formats = AK4671_FORMATS,},
|
||||
.ops = &ak4671_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ak4671_dai);
|
||||
|
||||
static int ak4671_probe(struct platform_device *pdev)
|
||||
static int ak4671_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
|
||||
if (ak4671_codec == NULL) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
codec->bias_level = SND_SOC_BIAS_OFF;
|
||||
|
||||
socdev->card->codec = ak4671_codec;
|
||||
codec = ak4671_codec;
|
||||
|
||||
/* register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
|
||||
goto pcm_err;
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_add_controls(codec, ak4671_snd_controls,
|
||||
|
@ -665,121 +657,48 @@ static int ak4671_probe(struct platform_device *pdev)
|
|||
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return ret;
|
||||
|
||||
pcm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ak4671_remove(struct platform_device *pdev)
|
||||
static int ak4671_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_ak4671 = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
|
||||
.probe = ak4671_probe,
|
||||
.remove = ak4671_remove,
|
||||
.set_bias_level = ak4671_set_bias_level,
|
||||
.reg_cache_size = AK4671_CACHEREGNUM,
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = ak4671_reg,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
|
||||
|
||||
static int ak4671_register(struct ak4671_priv *ak4671,
|
||||
enum snd_soc_control_type control)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_codec *codec = &ak4671->codec;
|
||||
|
||||
if (ak4671_codec) {
|
||||
dev_err(codec->dev, "Another AK4671 is registered\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, ak4671);
|
||||
codec->name = "AK4671";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->bias_level = SND_SOC_BIAS_OFF;
|
||||
codec->set_bias_level = ak4671_set_bias_level;
|
||||
codec->dai = &ak4671_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->reg_cache_size = AK4671_CACHEREGNUM;
|
||||
codec->reg_cache = &ak4671->reg_cache;
|
||||
|
||||
memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ak4671_dai.dev = codec->dev;
|
||||
ak4671_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&ak4671_dai);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
|
||||
goto err_codec;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_codec:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err:
|
||||
kfree(ak4671);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ak4671_unregister(struct ak4671_priv *ak4671)
|
||||
{
|
||||
ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
|
||||
snd_soc_unregister_dai(&ak4671_dai);
|
||||
snd_soc_unregister_codec(&ak4671->codec);
|
||||
kfree(ak4671);
|
||||
ak4671_codec = NULL;
|
||||
}
|
||||
|
||||
static int __devinit ak4671_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ak4671_priv *ak4671;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
|
||||
if (ak4671 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &ak4671->codec;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
|
||||
i2c_set_clientdata(client, ak4671);
|
||||
codec->control_data = client;
|
||||
ak4671->control_data = client;
|
||||
ak4671->control_type = SND_SOC_I2C;
|
||||
|
||||
codec->dev = &client->dev;
|
||||
|
||||
return ak4671_register(ak4671, SND_SOC_I2C);
|
||||
ret = snd_soc_register_codec(&client->dev,
|
||||
&soc_codec_dev_ak4671, &ak4671_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(ak4671);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int ak4671_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
|
||||
|
||||
ak4671_unregister(ak4671);
|
||||
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
|
|||
|
||||
static struct i2c_driver ak4671_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ak4671",
|
||||
.name = "ak4671-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ak4671_i2c_probe,
|
||||
|
|
|
@ -150,7 +150,4 @@
|
|||
/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
|
||||
#define AK4671_MUTEN 0x04
|
||||
|
||||
extern struct snd_soc_dai ak4671_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_dev_ak4671;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mfd/davinci_voicecodec.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -41,8 +42,6 @@
|
|||
|
||||
#include <mach/dm365.h>
|
||||
|
||||
#include "cq93vc.h"
|
||||
|
||||
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
|
@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {
|
|||
.set_sysclk = cq93vc_set_dai_sysclk,
|
||||
};
|
||||
|
||||
struct snd_soc_dai cq93vc_dai = {
|
||||
.name = "CQ93VC",
|
||||
static struct snd_soc_dai_driver cq93vc_dai = {
|
||||
.name = "cq93vc-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {
|
|||
.formats = CQ93VC_FORMATS,},
|
||||
.ops = &cq93vc_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cq93vc_dai);
|
||||
|
||||
static int cq93vc_resume(struct platform_device *pdev)
|
||||
static int cq93vc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec *cq93vc_codec;
|
||||
|
||||
static int cq93vc_probe(struct platform_device *pdev)
|
||||
static int cq93vc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
struct davinci_vc *davinci_vc = codec->dev->platform_data;
|
||||
|
||||
socdev->card->codec = cq93vc_codec;
|
||||
codec = socdev->card->codec;
|
||||
|
||||
/* Register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: failed to create pcms\n", pdev->name);
|
||||
return ret;
|
||||
}
|
||||
davinci_vc->cq93vc.codec = codec;
|
||||
codec->control_data = davinci_vc;
|
||||
|
||||
/* Set controls */
|
||||
snd_soc_add_controls(codec, cq93vc_snd_controls,
|
||||
|
@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cq93vc_remove(struct platform_device *pdev)
|
||||
static int cq93vc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_cq93vc = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
|
||||
.read = cq93vc_read,
|
||||
.write = cq93vc_write,
|
||||
.set_bias_level = cq93vc_set_bias_level,
|
||||
.probe = cq93vc_probe,
|
||||
.remove = cq93vc_remove,
|
||||
.resume = cq93vc_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
|
||||
|
||||
static __init int cq93vc_codec_probe(struct platform_device *pdev)
|
||||
static int cq93vc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL) {
|
||||
dev_dbg(davinci_vc->dev,
|
||||
"could not allocate memory for codec data\n");
|
||||
return -ENOMEM;
|
||||
return snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_cq93vc, &cq93vc_dai, 1);
|
||||
}
|
||||
|
||||
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);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
snd_soc_unregister_dai(&cq93vc_dai);
|
||||
snd_soc_unregister_codec(&codec);
|
||||
|
||||
kfree(codec);
|
||||
cq93vc_codec = NULL;
|
||||
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cq93vc_codec_driver = {
|
||||
.driver = {
|
||||
.name = "cq93vc",
|
||||
.name = "cq93vc-codec",
|
||||
.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);
|
||||
|
||||
static __exit void cq93vc_exit(void)
|
||||
static void __exit cq93vc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&cq93vc_codec_driver);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -31,8 +31,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "cs4270.h"
|
||||
|
||||
/*
|
||||
* The codec isn't really big-endian or little-endian, since the I2S
|
||||
* interface requires data to be sent serially with the MSbit first.
|
||||
|
@ -114,7 +112,8 @@ static const char *supply_names[] = {
|
|||
|
||||
/* Private data for the CS4270 */
|
||||
struct cs4270_private {
|
||||
struct snd_soc_codec codec;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[CS4270_NUMREGS];
|
||||
unsigned int mclk; /* Input frequency of the MCLK pin */
|
||||
unsigned int mode; /* The mode (I2S or left-justified) */
|
||||
|
@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int rates = 0;
|
||||
unsigned int rate_min = -1;
|
||||
unsigned int rate_max = 0;
|
||||
unsigned int i;
|
||||
|
||||
cs4270->mclk = freq;
|
||||
|
||||
if (cs4270->mclk) {
|
||||
for (i = 0; i < NUM_MCLK_RATIOS; i++) {
|
||||
unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
|
||||
rates |= snd_pcm_rate_to_rate_bit(rate);
|
||||
if (rate < rate_min)
|
||||
rate_min = rate;
|
||||
if (rate > rate_max)
|
||||
rate_max = rate;
|
||||
}
|
||||
/* FIXME: soc should support a rate list */
|
||||
rates &= ~SNDRV_PCM_RATE_KNOT;
|
||||
|
||||
if (!rates) {
|
||||
dev_err(codec->dev, "could not find a valid sample rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* enable all possible rates */
|
||||
rates = SNDRV_PCM_RATE_8000_192000;
|
||||
rate_min = 8000;
|
||||
rate_max = 192000;
|
||||
}
|
||||
|
||||
codec_dai->playback.rates = rates;
|
||||
codec_dai->playback.rate_min = rate_min;
|
||||
codec_dai->playback.rate_max = rate_max;
|
||||
|
||||
codec_dai->capture.rates = rates;
|
||||
codec_dai->capture.rate_min = rate_min;
|
||||
codec_dai->capture.rate_max = rate_max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
unsigned int i;
|
||||
|
@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
|
|||
snd_soc_get_volsw, cs4270_soc_put_mute),
|
||||
};
|
||||
|
||||
/*
|
||||
* cs4270_codec - global variable to store codec for the ASoC probe function
|
||||
*
|
||||
* If struct i2c_driver had a private_data field, we wouldn't need to use
|
||||
* cs4270_codec. This is the only way to pass the codec structure from
|
||||
* cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good
|
||||
* way to synchronize these two functions. cs4270_i2c_probe() can be called
|
||||
* multiple times before cs4270_probe() is called even once. So for now, we
|
||||
* also only allow cs4270_i2c_probe() to be run once. That means that we do
|
||||
* not support more than one cs4270 device in the system, at least for now.
|
||||
*/
|
||||
static struct snd_soc_codec *cs4270_codec;
|
||||
|
||||
static struct snd_soc_dai_ops cs4270_dai_ops = {
|
||||
.hw_params = cs4270_hw_params,
|
||||
.set_sysclk = cs4270_set_dai_sysclk,
|
||||
|
@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
|
|||
.digital_mute = cs4270_dai_mute,
|
||||
};
|
||||
|
||||
struct snd_soc_dai cs4270_dai = {
|
||||
.name = "cs4270",
|
||||
struct snd_soc_dai_driver cs4270_dai = {
|
||||
.name = "cs4270-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = 0,
|
||||
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.rate_min = 4000,
|
||||
.rate_max = 216000,
|
||||
.formats = CS4270_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = 0,
|
||||
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.rate_min = 4000,
|
||||
.rate_max = 216000,
|
||||
.formats = CS4270_FORMATS,
|
||||
},
|
||||
.ops = &cs4270_dai_ops,
|
||||
|
@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
|
|||
* This function is called when ASoC has all the pieces it needs to
|
||||
* instantiate a sound driver.
|
||||
*/
|
||||
static int cs4270_probe(struct platform_device *pdev)
|
||||
static int cs4270_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = cs4270_codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int i, ret;
|
||||
int i, ret, reg;
|
||||
|
||||
/* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
|
||||
socdev->card->codec = codec;
|
||||
|
||||
/* Register PCMs */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to create pcms\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add the non-DAPM controls */
|
||||
ret = snd_soc_add_controls(codec, cs4270_snd_controls,
|
||||
ARRAY_SIZE(cs4270_snd_controls));
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to add controls\n");
|
||||
goto error_free_pcms;
|
||||
}
|
||||
|
||||
/* get the power supply regulators */
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
cs4270->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
if (ret < 0)
|
||||
goto error_free_pcms;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
if (ret < 0)
|
||||
goto error_free_regulators;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_regulators:
|
||||
regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
|
||||
error_free_pcms:
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_remove - ASoC remove function
|
||||
* @pdev: platform device
|
||||
*
|
||||
* This function is the counterpart to cs4270_probe().
|
||||
*/
|
||||
static int cs4270_remove(struct platform_device *pdev)
|
||||
{
|
||||
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;
|
||||
codec->control_data = cs4270->control_data;
|
||||
|
||||
/* The I2C interface is set up, so pre-fill our register cache */
|
||||
|
||||
ret = cs4270_fill_cache(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to fill register cache\n");
|
||||
goto error_free_codec;
|
||||
dev_err(codec->dev, "failed to fill register cache\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable auto-mute. This feature appears to be buggy. In some
|
||||
|
@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
|
|||
reg &= ~CS4270_MUTE_AUTO;
|
||||
ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "i2c write failed\n");
|
||||
dev_err(codec->dev, "i2c write failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
|
|||
reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
|
||||
ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "i2c write failed\n");
|
||||
dev_err(codec->dev, "i2c write failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI
|
||||
* structure for each CS4270 device, but the machine driver needs to
|
||||
* have a pointer to the DAI structure, so for now it must be a global
|
||||
* variable.
|
||||
*/
|
||||
cs4270_dai.dev = &i2c_client->dev;
|
||||
|
||||
/* Register the DAI. If all the other ASoC driver have already
|
||||
* registered, then this will call our probe function, so
|
||||
* cs4270_codec needs to be ready.
|
||||
*/
|
||||
cs4270_codec = codec;
|
||||
ret = snd_soc_register_dai(&cs4270_dai);
|
||||
/* Add the non-DAPM controls */
|
||||
ret = snd_soc_add_controls(codec, cs4270_snd_controls,
|
||||
ARRAY_SIZE(cs4270_snd_controls));
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to register DAIe\n");
|
||||
goto error_free_codec;
|
||||
dev_err(codec->dev, "failed to add controls\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs4270);
|
||||
/* get the power supply regulators */
|
||||
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
|
||||
cs4270->supplies[i].supply = supply_names[i];
|
||||
|
||||
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
if (ret < 0)
|
||||
goto error_free_regulators;
|
||||
|
||||
return 0;
|
||||
|
||||
error_free_codec:
|
||||
kfree(cs4270);
|
||||
cs4270_codec = NULL;
|
||||
cs4270_dai.dev = NULL;
|
||||
error_free_regulators:
|
||||
regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
|
||||
cs4270->supplies);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs4270_i2c_remove - remove an I2C device
|
||||
* @i2c_client: the I2C client object
|
||||
* cs4270_remove - ASoC remove function
|
||||
* @pdev: platform device
|
||||
*
|
||||
* This function is the counterpart to cs4270_i2c_probe().
|
||||
* This function is the counterpart to cs4270_probe().
|
||||
*/
|
||||
static int cs4270_i2c_remove(struct i2c_client *i2c_client)
|
||||
static int cs4270_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client);
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
kfree(cs4270);
|
||||
cs4270_codec = NULL;
|
||||
cs4270_dai.dev = NULL;
|
||||
regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
|
||||
regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cs4270_id - I2C device IDs supported by this driver
|
||||
*/
|
||||
static struct i2c_device_id cs4270_id[] = {
|
||||
{"cs4270", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs4270_id);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
|
@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
|
|||
* and all registers are written back to the hardware when resuming.
|
||||
*/
|
||||
|
||||
static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
|
||||
static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
|
||||
{
|
||||
struct snd_soc_codec *codec = cs4270_codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
int reg, ret;
|
||||
|
||||
|
@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cs4270_soc_resume(struct platform_device *pdev)
|
||||
static int cs4270_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_codec *codec = cs4270_codec;
|
||||
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
|
||||
struct i2c_client *i2c_client = codec->control_data;
|
||||
int reg;
|
||||
|
@ -895,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
|
|||
#define cs4270_soc_resume NULL
|
||||
#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
|
||||
*
|
||||
|
@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
|
|||
*/
|
||||
static struct i2c_driver cs4270_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs4270",
|
||||
.name = "cs4270-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = cs4270_id,
|
||||
|
@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = {
|
|||
.remove = cs4270_i2c_remove,
|
||||
};
|
||||
|
||||
/*
|
||||
* ASoC codec device structure
|
||||
*
|
||||
* Assign this variable to the codec_dev field of the machine driver's
|
||||
* snd_soc_device structure.
|
||||
*/
|
||||
struct snd_soc_codec_device soc_codec_device_cs4270 = {
|
||||
.probe = cs4270_probe,
|
||||
.remove = cs4270_remove,
|
||||
.suspend = cs4270_soc_suspend,
|
||||
.resume = cs4270_soc_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
|
||||
|
||||
static int __init cs4270_init(void)
|
||||
{
|
||||
pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
|
||||
|
|
|
@ -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
|
|
@ -42,15 +42,14 @@ enum master_slave_mode {
|
|||
};
|
||||
|
||||
struct cs42l51_private {
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
unsigned int mclk;
|
||||
unsigned int audio_mode; /* The mode (I2S or left-justified) */
|
||||
enum master_slave_mode func;
|
||||
struct snd_soc_codec codec;
|
||||
u8 reg_cache[CS42L51_NUMREGS];
|
||||
};
|
||||
|
||||
static struct snd_soc_codec *cs42l51_codec;
|
||||
|
||||
#define CS42L51_FORMATS ( \
|
||||
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
|
||||
SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
|
||||
|
@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
struct cs42l51_private *cs42l51;
|
||||
int ret = 0;
|
||||
int reg;
|
||||
|
||||
if (cs42l51_codec)
|
||||
return -EBUSY;
|
||||
|
||||
/* Verify that we have a CS42L51 */
|
||||
ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to read I2C\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
|
||||
(ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
|
||||
dev_err(&i2c_client->dev, "Invalid chip id\n");
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
|
||||
ret & 7);
|
||||
|
||||
cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
|
||||
if (!cs42l51) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
codec = &cs42l51->codec;
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
codec->dev = &i2c_client->dev;
|
||||
codec->name = "CS42L51";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &cs42l51_dai;
|
||||
codec->num_dai = 1;
|
||||
snd_soc_codec_set_drvdata(codec, cs42l51);
|
||||
|
||||
codec->control_data = i2c_client;
|
||||
codec->reg_cache = cs42l51->reg_cache;
|
||||
codec->reg_cache_size = CS42L51_NUMREGS;
|
||||
i2c_set_clientdata(i2c_client, codec);
|
||||
|
||||
ret = cs42l51_fill_cache(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to fill register cache\n");
|
||||
goto error_alloc;
|
||||
}
|
||||
|
||||
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
|
||||
goto error_alloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* DAC configuration
|
||||
* - Use signal processor
|
||||
* - auto mute
|
||||
* - vol changes immediate
|
||||
* - no de-emphasize
|
||||
*/
|
||||
reg = CS42L51_DAC_CTL_DATA_SEL(1)
|
||||
| CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
|
||||
ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
|
||||
if (ret < 0)
|
||||
goto error_alloc;
|
||||
|
||||
cs42l51_dai.dev = codec->dev;
|
||||
cs42l51_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret != 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto error_alloc;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&cs42l51_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to register DAIe\n");
|
||||
goto error_reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_reg:
|
||||
snd_soc_unregister_codec(codec);
|
||||
error_alloc:
|
||||
kfree(cs42l51);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs42l51_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
|
||||
snd_soc_unregister_dai(&cs42l51_dai);
|
||||
snd_soc_unregister_codec(cs42l51_codec);
|
||||
cs42l51_codec = NULL;
|
||||
kfree(cs42l51);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct i2c_device_id cs42l51_id[] = {
|
||||
{"cs42l51", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
|
||||
|
||||
static struct i2c_driver cs42l51_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "CS42L51 I2C",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = cs42l51_id,
|
||||
.probe = cs42l51_i2c_probe,
|
||||
.remove = cs42l51_i2c_remove,
|
||||
};
|
||||
|
||||
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|||
{
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
struct cs42l51_ratios *ratios = NULL;
|
||||
int nr_ratios = 0;
|
||||
unsigned int rates = 0;
|
||||
unsigned int rate_min = -1;
|
||||
unsigned int rate_max = 0;
|
||||
int i;
|
||||
|
||||
cs42l51->mclk = freq;
|
||||
|
||||
switch (cs42l51->func) {
|
||||
case MODE_MASTER:
|
||||
return -EINVAL;
|
||||
case MODE_SLAVE:
|
||||
ratios = slave_ratios;
|
||||
nr_ratios = ARRAY_SIZE(slave_ratios);
|
||||
break;
|
||||
case MODE_SLAVE_AUTO:
|
||||
ratios = slave_auto_ratios;
|
||||
nr_ratios = ARRAY_SIZE(slave_auto_ratios);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ratios; i++) {
|
||||
unsigned int rate = freq / ratios[i].ratio;
|
||||
rates |= snd_pcm_rate_to_rate_bit(rate);
|
||||
if (rate < rate_min)
|
||||
rate_min = rate;
|
||||
if (rate > rate_max)
|
||||
rate_max = rate;
|
||||
}
|
||||
rates &= ~SNDRV_PCM_RATE_KNOT;
|
||||
|
||||
if (!rates) {
|
||||
dev_err(codec->dev, "could not find a valid sample rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
codec_dai->playback.rates = rates;
|
||||
codec_dai->playback.rate_min = rate_min;
|
||||
codec_dai->playback.rate_max = rate_max;
|
||||
|
||||
codec_dai->capture.rates = rates;
|
||||
codec_dai->capture.rate_min = rate_min;
|
||||
codec_dai->capture.rate_max = rate_max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret;
|
||||
unsigned int i;
|
||||
|
@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {
|
|||
.digital_mute = cs42l51_dai_mute,
|
||||
};
|
||||
|
||||
struct snd_soc_dai cs42l51_dai = {
|
||||
.name = "CS42L51 HiFi",
|
||||
static struct snd_soc_dai_driver cs42l51_dai = {
|
||||
.name = "cs42l51-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {
|
|||
},
|
||||
.ops = &cs42l51_dai_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cs42l51_dai);
|
||||
|
||||
|
||||
static int cs42l51_probe(struct platform_device *pdev)
|
||||
static int cs42l51_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret = 0;
|
||||
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
|
||||
int ret, reg;
|
||||
|
||||
if (!cs42l51_codec) {
|
||||
dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
codec->control_data = cs42l51->control_data;
|
||||
|
||||
socdev->card->codec = cs42l51_codec;
|
||||
codec = socdev->card->codec;
|
||||
|
||||
/* Register PCMs */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
ret = cs42l51_fill_cache(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to create PCMs\n");
|
||||
dev_err(codec->dev, "failed to fill register cache\n");
|
||||
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,
|
||||
ARRAY_SIZE(cs42l51_snd_controls));
|
||||
snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
|
||||
|
@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
|
||||
.probe = cs42l51_probe,
|
||||
.reg_cache_size = CS42L51_NUMREGS,
|
||||
.reg_word_size = sizeof(u8),
|
||||
};
|
||||
|
||||
static int cs42l51_remove(struct platform_device *pdev)
|
||||
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct cs42l51_private *cs42l51;
|
||||
int ret;
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
/* Verify that we have a CS42L51 */
|
||||
ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c_client->dev, "failed to read I2C\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
|
||||
(ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
|
||||
dev_err(&i2c_client->dev, "Invalid chip id\n");
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
|
||||
ret & 7);
|
||||
|
||||
cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
|
||||
if (!cs42l51) {
|
||||
dev_err(&i2c_client->dev, "could not allocate codec\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c_client, cs42l51);
|
||||
cs42l51->control_data = i2c_client;
|
||||
cs42l51->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = snd_soc_register_codec(&i2c_client->dev,
|
||||
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(cs42l51);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs42l51_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
|
||||
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(cs42l51);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_device_cs42l51 = {
|
||||
.probe = cs42l51_probe,
|
||||
.remove = cs42l51_remove
|
||||
static const struct i2c_device_id cs42l51_id[] = {
|
||||
{"cs42l51", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
|
||||
|
||||
static struct i2c_driver cs42l51_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs42L51-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = cs42l51_id,
|
||||
.probe = cs42l51_i2c_probe,
|
||||
.remove = cs42l51_i2c_remove,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
|
||||
|
||||
static int __init cs42l51_init(void)
|
||||
{
|
||||
|
|
|
@ -158,6 +158,4 @@
|
|||
#define CS42L51_LASTREG 0x20
|
||||
#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
|
||||
|
||||
extern struct snd_soc_dai cs42l51_dai;
|
||||
extern struct snd_soc_codec_device soc_codec_device_cs42l51;
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
|
||||
struct cx20442_priv {
|
||||
struct snd_soc_codec codec;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
u8 reg_cache[1];
|
||||
};
|
||||
|
||||
|
@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
|
|||
{
|
||||
u8 *reg_cache = codec->reg_cache;
|
||||
|
||||
if (reg >= codec->reg_cache_size)
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EINVAL;
|
||||
|
||||
return reg_cache[reg];
|
||||
|
@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)
|
|||
static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
|
||||
u8 *reg_cache = codec->reg_cache;
|
||||
int vls, vsp, old, len;
|
||||
char buf[18];
|
||||
|
||||
if (reg >= codec->reg_cache_size)
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EINVAL;
|
||||
|
||||
/* hw_write and control_data pointers required for talking to the modem
|
||||
* are expected to be set by the line discipline initialization code */
|
||||
if (!codec->hw_write || !codec->control_data)
|
||||
if (!codec->hw_write || !cx20442->control_data)
|
||||
return -EIO;
|
||||
|
||||
old = reg_cache[reg];
|
||||
|
@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
return -ENOMEM;
|
||||
|
||||
dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
|
||||
if (codec->hw_write(codec->control_data, buf, len) != len)
|
||||
if (codec->hw_write(cx20442->control_data, buf, len) != len)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Moved up here as line discipline referres it during initialization */
|
||||
static struct snd_soc_codec *cx20442_codec;
|
||||
|
||||
|
||||
/*
|
||||
* Line discpline related code
|
||||
*
|
||||
|
@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";
|
|||
/* Line discipline .open() */
|
||||
static int v253_open(struct tty_struct *tty)
|
||||
{
|
||||
struct snd_soc_codec *codec = cx20442_codec;
|
||||
int ret, len = strlen(v253_init);
|
||||
|
||||
/* Doesn't make sense without write callback */
|
||||
if (!tty->ops->write)
|
||||
return -EINVAL;
|
||||
|
||||
/* Pass the codec structure address for use by other ldisc callbacks */
|
||||
tty->disc_data = codec;
|
||||
/* Won't work if no codec pointer has been passed by a card driver */
|
||||
if (!tty->disc_data)
|
||||
return -ENODEV;
|
||||
|
||||
if (tty->ops->write(tty, v253_init, len) != len) {
|
||||
ret = -EIO;
|
||||
|
@ -253,15 +251,18 @@ err:
|
|||
static void v253_close(struct tty_struct *tty)
|
||||
{
|
||||
struct snd_soc_codec *codec = tty->disc_data;
|
||||
struct cx20442_priv *cx20442;
|
||||
|
||||
tty->disc_data = NULL;
|
||||
|
||||
if (!codec)
|
||||
return;
|
||||
|
||||
cx20442 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
/* Prevent the codec driver from further accessing the modem */
|
||||
codec->hw_write = NULL;
|
||||
codec->control_data = NULL;
|
||||
cx20442->control_data = NULL;
|
||||
codec->pop_time = 0;
|
||||
}
|
||||
|
||||
|
@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,
|
|||
const unsigned char *cp, char *fp, int count)
|
||||
{
|
||||
struct snd_soc_codec *codec = tty->disc_data;
|
||||
struct cx20442_priv *cx20442;
|
||||
|
||||
if (!codec)
|
||||
return;
|
||||
|
||||
if (!codec->control_data) {
|
||||
cx20442 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (!cx20442->control_data) {
|
||||
/* First modem response, complete setup procedure */
|
||||
|
||||
/* Set up codec driver access to modem controls */
|
||||
codec->control_data = tty;
|
||||
cx20442->control_data = tty;
|
||||
codec->hw_write = (hw_write_t)tty->ops->write;
|
||||
codec->pop_time = 1;
|
||||
}
|
||||
|
@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);
|
|||
* Codec DAI
|
||||
*/
|
||||
|
||||
struct snd_soc_dai cx20442_dai = {
|
||||
.name = "CX20442",
|
||||
static struct snd_soc_dai_driver cx20442_dai = {
|
||||
.name = "cx20442-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cx20442_dai);
|
||||
|
||||
static int cx20442_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
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)
|
||||
static int cx20442_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cx20442_priv *cx20442;
|
||||
struct snd_soc_codec *codec;
|
||||
|
||||
cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
|
||||
if (cx20442 == NULL)
|
||||
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->pop_time = 0;
|
||||
|
||||
codec->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, cx20442);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
|
||||
|
||||
cx20442_unregister(cx20442);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cx20442_platform_driver = {
|
||||
.driver = {
|
||||
.name = "cx20442",
|
||||
.name = "cx20442-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = cx20442_platform_probe,
|
||||
|
@ -487,4 +412,4 @@ module_exit(cx20442_exit);
|
|||
MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
|
||||
MODULE_AUTHOR("Janusz Krzysztofik");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:cx20442");
|
||||
MODULE_ALIAS("platform:cx20442-codec");
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#ifndef _CX20442_CODEC_H
|
||||
#define _CX20442_CODEC_H
|
||||
|
||||
extern struct snd_soc_dai cx20442_dai;
|
||||
extern struct snd_soc_codec_device cx20442_codec_dev;
|
||||
extern struct tty_ldisc_ops v253_ops;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "da7210.h"
|
||||
|
||||
/* DA7210 register space */
|
||||
#define DA7210_STATUS 0x02
|
||||
#define DA7210_STARTUP1 0x03
|
||||
|
@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
|
|||
|
||||
/* Codec private data */
|
||||
struct da7210_priv {
|
||||
struct snd_soc_codec codec;
|
||||
enum snd_soc_control_type control_type;
|
||||
void *control_data;
|
||||
};
|
||||
|
||||
static struct snd_soc_codec *da7210_codec;
|
||||
|
||||
/*
|
||||
* Register cache
|
||||
*/
|
||||
|
@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
|
|||
u8 *cache = codec->reg_cache;
|
||||
u8 data[2];
|
||||
|
||||
BUG_ON(codec->volatile_register);
|
||||
BUG_ON(codec->driver->volatile_register);
|
||||
|
||||
data[0] = reg & 0xff;
|
||||
data[1] = value & 0xff;
|
||||
|
||||
if (reg >= codec->reg_cache_size)
|
||||
if (reg >= codec->driver->reg_cache_size)
|
||||
return -EIO;
|
||||
|
||||
if (2 != codec->hw_write(codec->control_data, data, 2))
|
||||
|
@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
u32 dai_cfg1;
|
||||
u32 hpf_reg, hpf_mask, hpf_value;
|
||||
u32 fs, bypass;
|
||||
|
@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {
|
|||
.set_fmt = da7210_set_dai_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai da7210_dai = {
|
||||
.name = "DA7210 IIS",
|
||||
.id = 0,
|
||||
static struct snd_soc_dai_driver da7210_dai = {
|
||||
.name = "da7210-hifi",
|
||||
/* playback capabilities */
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
|
@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {
|
|||
.ops = &da7210_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(da7210_dai);
|
||||
|
||||
/*
|
||||
* Initialize the DA7210 driver
|
||||
* register the mixer and dsp interfaces with the kernel
|
||||
*/
|
||||
static int da7210_init(struct da7210_priv *da7210)
|
||||
static int da7210_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_codec *codec = &da7210->codec;
|
||||
int ret = 0;
|
||||
struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
if (da7210_codec) {
|
||||
dev_err(codec->dev, "Another da7210 is registered\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, da7210);
|
||||
codec->name = "DA7210";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->read = da7210_read;
|
||||
codec->write = da7210_write;
|
||||
codec->dai = &da7210_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->control_data = da7210->control_data;
|
||||
codec->hw_write = (hw_write_t)i2c_master_send;
|
||||
codec->reg_cache_size = ARRAY_SIZE(da7210_reg);
|
||||
codec->reg_cache = kmemdup(da7210_reg,
|
||||
sizeof(da7210_reg), GFP_KERNEL);
|
||||
|
||||
if (!codec->reg_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
da7210_dai.dev = codec->dev;
|
||||
da7210_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to register CODEC: %d\n", ret);
|
||||
goto init_err;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&da7210_dai);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
|
||||
goto codec_err;
|
||||
}
|
||||
|
||||
/* FIXME
|
||||
*
|
||||
|
@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)
|
|||
/* Activate all enabled subsystem */
|
||||
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
|
||||
|
||||
return ret;
|
||||
snd_soc_add_controls(codec, da7210_snd_controls,
|
||||
ARRAY_SIZE(da7210_snd_controls));
|
||||
|
||||
codec_err:
|
||||
snd_soc_unregister_codec(codec);
|
||||
init_err:
|
||||
kfree(codec->reg_cache);
|
||||
codec->reg_cache = NULL;
|
||||
|
||||
return ret;
|
||||
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
|
||||
.probe = da7210_probe,
|
||||
.read = da7210_read,
|
||||
.write = da7210_write,
|
||||
.reg_cache_size = ARRAY_SIZE(da7210_reg),
|
||||
.reg_word_size = sizeof(u8),
|
||||
.reg_cache_default = da7210_reg,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
||||
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct da7210_priv *da7210;
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
|
||||
if (!da7210)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = &da7210->codec;
|
||||
codec->dev = &i2c->dev;
|
||||
|
||||
i2c_set_clientdata(i2c, da7210);
|
||||
codec->control_data = i2c;
|
||||
da7210->control_data = i2c;
|
||||
da7210->control_type = SND_SOC_I2C;
|
||||
|
||||
ret = da7210_init(da7210);
|
||||
if (ret < 0) {
|
||||
pr_err("Failed to initialise da7210 audio codec\n");
|
||||
ret = snd_soc_register_codec(&i2c->dev,
|
||||
&soc_codec_dev_da7210, &da7210_dai, 1);
|
||||
if (ret < 0)
|
||||
kfree(da7210);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da7210_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct da7210_priv *da7210 = i2c_get_clientdata(client);
|
||||
|
||||
snd_soc_unregister_dai(&da7210_dai);
|
||||
kfree(da7210->codec.reg_cache);
|
||||
kfree(da7210);
|
||||
da7210_codec = NULL;
|
||||
|
||||
snd_soc_unregister_codec(&client->dev);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
|
|||
/* I2C codec control layer */
|
||||
static struct i2c_driver da7210_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "DA7210 I2C Codec",
|
||||
.name = "da7210-codec",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da7210_i2c_probe,
|
||||
|
@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static int da7210_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
if (!da7210_codec) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
socdev->card->codec = da7210_codec;
|
||||
codec = da7210_codec;
|
||||
|
||||
/* Register pcms */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0)
|
||||
goto pcm_err;
|
||||
|
||||
snd_soc_add_controls(da7210_codec, da7210_snd_controls,
|
||||
ARRAY_SIZE(da7210_snd_controls));
|
||||
|
||||
dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
|
||||
|
||||
pcm_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da7210_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_da7210 = {
|
||||
.probe = da7210_probe,
|
||||
.remove = da7210_remove,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_da7210);
|
||||
|
||||
static int __init da7210_modinit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
@ -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
|
||||
|
|
@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {
|
|||
struct jz4740_codec {
|
||||
void __iomem *base;
|
||||
struct resource *mem;
|
||||
|
||||
uint32_t reg_cache[2];
|
||||
struct snd_soc_codec codec;
|
||||
};
|
||||
|
||||
static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
|
||||
{
|
||||
return container_of(codec, struct jz4740_codec, codec);
|
||||
}
|
||||
|
||||
static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
|
||||
struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
|
||||
return readl(jz4740_codec->base + (reg << 2));
|
||||
}
|
||||
|
||||
static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
|
||||
struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
|
||||
u32 *cache = codec->reg_cache;
|
||||
|
||||
jz4740_codec->reg_cache[reg] = val;
|
||||
cache[reg] = val;
|
||||
writel(val, jz4740_codec->base + (reg << 2));
|
||||
|
||||
return 0;
|
||||
|
@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
uint32_t val;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_device *socdev = rtd->socdev;
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct snd_soc_codec *codec =rtd->codec;
|
||||
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
|
@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
|
|||
.hw_params = jz4740_codec_hw_params,
|
||||
};
|
||||
|
||||
struct snd_soc_dai jz4740_codec_dai = {
|
||||
.name = "jz4740",
|
||||
static struct snd_soc_dai_driver jz4740_codec_dai = {
|
||||
.name = "jz4740-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
|
@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {
|
|||
.ops = &jz4740_codec_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(jz4740_codec_dai);
|
||||
|
||||
static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
|
||||
{
|
||||
|
@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec *jz4740_codec_codec;
|
||||
|
||||
static int jz4740_codec_dev_probe(struct platform_device *pdev)
|
||||
static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
int ret;
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = jz4740_codec_codec;
|
||||
|
||||
BUG_ON(!codec);
|
||||
|
||||
socdev->card->codec = codec;
|
||||
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
|
||||
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
|
||||
|
||||
snd_soc_add_controls(codec, jz4740_codec_controls,
|
||||
ARRAY_SIZE(jz4740_codec_controls));
|
||||
|
@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev)
|
|||
|
||||
snd_soc_dapm_new_widgets(codec);
|
||||
|
||||
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4740_codec_dev_remove(struct platform_device *pdev)
|
||||
static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
snd_soc_dapm_free(socdev);
|
||||
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
|
||||
}
|
||||
|
||||
static int jz4740_codec_resume(struct platform_device *pdev)
|
||||
static int jz4740_codec_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
|
||||
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
}
|
||||
|
||||
|
@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev)
|
|||
#define jz4740_codec_resume NULL
|
||||
#endif
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
|
||||
.probe = jz4740_codec_dev_probe,
|
||||
.remove = jz4740_codec_dev_remove,
|
||||
.suspend = jz4740_codec_suspend,
|
||||
.resume = jz4740_codec_resume,
|
||||
.read = jz4740_codec_read,
|
||||
.write = jz4740_codec_write,
|
||||
.set_bias_level = jz4740_codec_set_bias_level,
|
||||
.reg_cache_default = jz4740_codec_regs,
|
||||
.reg_word_size = sizeof(u32),
|
||||
.reg_cache_size = 2,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
|
||||
|
||||
static int __devinit jz4740_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct jz4740_codec *jz4740_codec;
|
||||
struct snd_soc_codec *codec;
|
||||
struct resource *mem;
|
||||
|
||||
jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
|
||||
|
@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
|
|||
}
|
||||
jz4740_codec->mem = mem;
|
||||
|
||||
jz4740_codec_dai.dev = &pdev->dev;
|
||||
|
||||
codec = &jz4740_codec->codec;
|
||||
|
||||
codec->dev = &pdev->dev;
|
||||
codec->name = "jz4740";
|
||||
codec->owner = THIS_MODULE;
|
||||
|
||||
codec->read = jz4740_codec_read;
|
||||
codec->write = jz4740_codec_write;
|
||||
codec->set_bias_level = jz4740_codec_set_bias_level;
|
||||
codec->bias_level = SND_SOC_BIAS_OFF;
|
||||
|
||||
codec->dai = &jz4740_codec_dai;
|
||||
codec->num_dai = 1;
|
||||
|
||||
codec->reg_cache = jz4740_codec->reg_cache;
|
||||
codec->reg_cache_size = 2;
|
||||
memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
jz4740_codec_codec = codec;
|
||||
|
||||
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
|
||||
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
|
||||
|
||||
platform_set_drvdata(pdev, jz4740_codec);
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
ret = snd_soc_register_codec(&pdev->dev,
|
||||
&soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to register codec\n");
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_dai(&jz4740_codec_dai);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to register codec dai\n");
|
||||
goto err_unregister_codec;
|
||||
}
|
||||
|
||||
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_codec:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err_iounmap:
|
||||
iounmap(jz4740_codec->base);
|
||||
err_release_mem_region:
|
||||
|
@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
|
|||
struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
|
||||
struct resource *mem = jz4740_codec->mem;
|
||||
|
||||
snd_soc_unregister_dai(&jz4740_codec_dai);
|
||||
snd_soc_unregister_codec(&jz4740_codec->codec);
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
|
||||
iounmap(jz4740_codec->base);
|
||||
release_mem_region(mem->start, resource_size(mem));
|
||||
|
|
|
@ -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
|
|
@ -32,8 +32,8 @@
|
|||
#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
SNDRV_PCM_RATE_48000)
|
||||
|
||||
struct snd_soc_dai pcm3008_dai = {
|
||||
.name = "PCM3008 HiFi",
|
||||
static struct snd_soc_dai_driver pcm3008_dai = {
|
||||
.name = "pcm3008-hifi",
|
||||
.playback = {
|
||||
.stream_name = "PCM3008 Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {
|
|||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(pcm3008_dai);
|
||||
|
||||
static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
|
||||
{
|
||||
|
@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
|
|||
gpio_free(setup->pdda_pin);
|
||||
}
|
||||
|
||||
static int pcm3008_soc_probe(struct platform_device *pdev)
|
||||
static int pcm3008_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
struct pcm3008_setup_data *setup = socdev->codec_data;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
int ret = 0;
|
||||
|
||||
printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
|
||||
|
||||
socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (!socdev->card->codec)
|
||||
return -ENOMEM;
|
||||
|
||||
codec = socdev->card->codec;
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
codec->name = "PCM3008";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &pcm3008_dai;
|
||||
codec->num_dai = 1;
|
||||
codec->write = NULL;
|
||||
codec->read = NULL;
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
/* Register PCMs. */
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "pcm3008: failed to create pcms\n");
|
||||
goto pcm_err;
|
||||
}
|
||||
|
||||
/* DEM1 DEM0 DE-EMPHASIS_MODE
|
||||
* Low Low De-emphasis 44.1 kHz ON
|
||||
* Low High De-emphasis OFF
|
||||
|
@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
|
|||
|
||||
gpio_err:
|
||||
pcm3008_gpio_free(setup);
|
||||
pcm_err:
|
||||
kfree(socdev->card->codec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pcm3008_soc_remove(struct platform_device *pdev)
|
||||
static int pcm3008_soc_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec = socdev->card->codec;
|
||||
struct pcm3008_setup_data *setup = socdev->codec_data;
|
||||
|
||||
if (!codec)
|
||||
return 0;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
pcm3008_gpio_free(setup);
|
||||
snd_soc_free_pcms(socdev);
|
||||
kfree(socdev->card->codec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
|
||||
static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct pcm3008_setup_data *setup = socdev->codec_data;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value(setup->pdad_pin, 0);
|
||||
gpio_set_value(setup->pdda_pin, 0);
|
||||
|
@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pcm3008_soc_resume(struct platform_device *pdev)
|
||||
static int pcm3008_soc_resume(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct pcm3008_setup_data *setup = socdev->codec_data;
|
||||
struct pcm3008_setup_data *setup = codec->dev->platform_data;
|
||||
|
||||
gpio_set_value(setup->pdad_pin, 1);
|
||||
gpio_set_value(setup->pdda_pin, 1);
|
||||
|
@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev)
|
|||
#define pcm3008_soc_resume NULL
|
||||
#endif
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
|
||||
static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
|
||||
.probe = pcm3008_soc_probe,
|
||||
.remove = pcm3008_soc_remove,
|
||||
.suspend = pcm3008_soc_suspend,
|
||||
.resume = pcm3008_soc_resume,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
|
||||
|
||||
static int __init pcm3008_init(void)
|
||||
static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
return snd_soc_register_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)
|
||||
{
|
||||
snd_soc_unregister_dai(&pcm3008_dai);
|
||||
platform_driver_unregister(&pcm3008_codec_driver);
|
||||
}
|
||||
module_exit(pcm3008_exit);
|
||||
|
||||
|
|
|
@ -19,7 +19,4 @@ struct pcm3008_setup_data {
|
|||
unsigned pdda_pin;
|
||||
};
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
|
||||
extern struct snd_soc_dai pcm3008_dai;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,57 +21,16 @@
|
|||
#include <sound/pcm.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "spdif_transciever.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define STUB_RATES SNDRV_PCM_RATE_8000_96000
|
||||
#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
|
||||
|
||||
static struct snd_soc_codec *spdif_dit_codec;
|
||||
|
||||
static int spdif_dit_codec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
static struct snd_soc_codec_driver soc_codec_spdif_dit;
|
||||
|
||||
if (spdif_dit_codec == NULL) {
|
||||
dev_err(&pdev->dev, "Codec device not registered\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
socdev->card->codec = spdif_dit_codec;
|
||||
codec = spdif_dit_codec;
|
||||
|
||||
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
|
||||
goto err_create_pcms;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_create_pcms:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spdif_dit_codec_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_free_pcms(socdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snd_soc_codec_device soc_codec_dev_spdif_dit = {
|
||||
.probe = spdif_dit_codec_probe,
|
||||
.remove = spdif_dit_codec_remove,
|
||||
}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
|
||||
|
||||
struct snd_soc_dai dit_stub_dai = {
|
||||
.name = "DIT",
|
||||
static struct snd_soc_dai_driver dit_stub_dai = {
|
||||
.name = "dit-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
|
@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = {
|
|||
.formats = STUB_FORMATS,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(dit_stub_dai);
|
||||
|
||||
static int spdif_dit_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_codec *codec;
|
||||
int ret;
|
||||
|
||||
if (spdif_dit_codec) {
|
||||
dev_err(&pdev->dev, "Another Codec is registered\n");
|
||||
ret = -EINVAL;
|
||||
goto err_reg_codec;
|
||||
}
|
||||
|
||||
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
|
||||
if (codec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->dev = &pdev->dev;
|
||||
|
||||
mutex_init(&codec->mutex);
|
||||
|
||||
INIT_LIST_HEAD(&codec->dapm_widgets);
|
||||
INIT_LIST_HEAD(&codec->dapm_paths);
|
||||
|
||||
codec->name = "spdif-dit";
|
||||
codec->owner = THIS_MODULE;
|
||||
codec->dai = &dit_stub_dai;
|
||||
codec->num_dai = 1;
|
||||
|
||||
spdif_dit_codec = codec;
|
||||
|
||||
ret = snd_soc_register_codec(codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
|
||||
goto err_reg_codec;
|
||||
}
|
||||
|
||||
dit_stub_dai.dev = &pdev->dev;
|
||||
ret = snd_soc_register_dai(&dit_stub_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Failed to register dai: %d\n", ret);
|
||||
goto err_reg_dai;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_dai:
|
||||
snd_soc_unregister_codec(codec);
|
||||
err_reg_codec:
|
||||
kfree(spdif_dit_codec);
|
||||
return ret;
|
||||
return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
|
||||
&dit_stub_dai, 1);
|
||||
}
|
||||
|
||||
static int spdif_dit_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_dai(&dit_stub_dai);
|
||||
snd_soc_unregister_codec(spdif_dit_codec);
|
||||
kfree(spdif_dit_codec);
|
||||
spdif_dit_codec = NULL;
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* ALSA SoC DIT/DIR driver header
|
||||
*
|
||||
* Author: Steve Chen, <schen@mvista.com>
|
||||
* Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef CODEC_STUBS_H
|
||||
#define CODEC_STUBS_H
|
||||
|
||||
extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
|
||||
extern struct snd_soc_dai dit_stub_dai;
|
||||
|
||||
#endif /* CODEC_STUBS_H */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue