From 5539aa8375761668214ea53a784d3adbefe89784 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 6 Mar 2012 18:13:25 +0000 Subject: [PATCH] --- yaml --- r: 293488 b: refs/heads/master c: f1e90af2b55ee13a3ed5ee1b9229d0edefeff27c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/mach-omap1/Kconfig | 3 + trunk/arch/arm/mach-omap1/Makefile | 4 +- trunk/arch/arm/mach-omap1/devices.c | 9 + trunk/arch/arm/mach-omap1/mcbsp.c | 14 +- trunk/arch/arm/mach-omap2/Makefile | 4 +- trunk/arch/arm/mach-omap2/board-omap4panda.c | 2 +- trunk/arch/arm/mach-omap2/devices.c | 22 + trunk/arch/arm/mach-omap2/mcbsp.c | 54 +- trunk/arch/arm/plat-omap/Kconfig | 8 + trunk/arch/arm/plat-omap/Makefile | 2 + trunk/arch/arm/plat-omap/include/plat/mcbsp.h | 333 +++++++++++ .../soc/omap => arch/arm/plat-omap}/mcbsp.c | 549 ++++++++++++++---- trunk/sound/soc/omap/Kconfig | 2 + trunk/sound/soc/omap/Makefile | 2 +- trunk/sound/soc/omap/am3517evm.c | 2 +- trunk/sound/soc/omap/ams-delta.c | 2 +- trunk/sound/soc/omap/igep0020.c | 2 +- trunk/sound/soc/omap/mcbsp.h | 346 ----------- trunk/sound/soc/omap/n810.c | 2 +- trunk/sound/soc/omap/omap-mcbsp.c | 321 +++++----- trunk/sound/soc/omap/omap-mcbsp.h | 2 +- trunk/sound/soc/omap/omap-pcm.h | 2 - trunk/sound/soc/omap/omap3beagle.c | 2 +- trunk/sound/soc/omap/omap3evm.c | 2 +- trunk/sound/soc/omap/omap3pandora.c | 4 +- trunk/sound/soc/omap/osk5912.c | 2 +- trunk/sound/soc/omap/overo.c | 2 +- trunk/sound/soc/omap/rx51.c | 4 +- trunk/sound/soc/omap/sdp3430.c | 4 +- trunk/sound/soc/omap/zoom2.c | 4 +- trunk/sound/soc/soc-dapm.c | 2 +- 32 files changed, 1007 insertions(+), 708 deletions(-) rename trunk/{sound/soc/omap => arch/arm/plat-omap}/mcbsp.c (66%) delete mode 100644 trunk/sound/soc/omap/mcbsp.h diff --git a/[refs] b/[refs] index d5be909817e6..d5b282be0715 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d0f47ff17f29740eabbd64e11705b7332241714c +refs/heads/master: f1e90af2b55ee13a3ed5ee1b9229d0edefeff27c diff --git a/trunk/arch/arm/mach-omap1/Kconfig b/trunk/arch/arm/mach-omap1/Kconfig index 922ab0dc2bcd..4f8d66f044e7 100644 --- a/trunk/arch/arm/mach-omap1/Kconfig +++ b/trunk/arch/arm/mach-omap1/Kconfig @@ -37,6 +37,7 @@ comment "OMAP Board Type" config MACH_OMAP_INNOVATOR bool "TI Innovator" depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) + select OMAP_MCBSP help TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. @@ -44,6 +45,7 @@ config MACH_OMAP_INNOVATOR config MACH_OMAP_H2 bool "TI H2 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX + select OMAP_MCBSP help TI OMAP 1610/1611B H2 board support. Say Y here if you have such a board. @@ -70,6 +72,7 @@ config MACH_HERALD config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX + select OMAP_MCBSP help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. diff --git a/trunk/arch/arm/mach-omap1/Makefile b/trunk/arch/arm/mach-omap1/Makefile index 9923f92b5450..11c85cd2731a 100644 --- a/trunk/arch/arm/mach-omap1/Makefile +++ b/trunk/arch/arm/mach-omap1/Makefile @@ -6,9 +6,7 @@ obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o -ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),) -obj-y += mcbsp.o -endif +obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o diff --git a/trunk/arch/arm/mach-omap1/devices.c b/trunk/arch/arm/mach-omap1/devices.c index 187b2fe132e9..1d76a63c0983 100644 --- a/trunk/arch/arm/mach-omap1/devices.c +++ b/trunk/arch/arm/mach-omap1/devices.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "clock.h" @@ -249,8 +250,16 @@ static struct platform_device omap_pcm = { .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); } diff --git a/trunk/arch/arm/mach-omap1/mcbsp.c b/trunk/arch/arm/mach-omap1/mcbsp.c index 3e8410a99990..91f9abbd3250 100644 --- a/trunk/arch/arm/mach-omap1/mcbsp.c +++ b/trunk/arch/arm/mach-omap1/mcbsp.c @@ -419,6 +419,18 @@ static int __init omap1_mcbsp_init(void) if (!cpu_class_is_omap1()) return -ENODEV; + if (cpu_is_omap7xx()) + omap_mcbsp_count = OMAP7XX_MCBSP_COUNT; + else if (cpu_is_omap15xx()) + omap_mcbsp_count = OMAP15XX_MCBSP_COUNT; + else if (cpu_is_omap16xx()) + omap_mcbsp_count = OMAP16XX_MCBSP_COUNT; + + mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), + GFP_KERNEL); + if (!mcbsp_ptr) + return -ENOMEM; + if (cpu_is_omap7xx()) omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0, OMAP7XX_MCBSP_RES_SZ, @@ -437,7 +449,7 @@ static int __init omap1_mcbsp_init(void) omap16xx_mcbsp_pdata, OMAP16XX_MCBSP_COUNT); - return 0; + return omap_mcbsp_init(); } arch_initcall(omap1_mcbsp_init); diff --git a/trunk/arch/arm/mach-omap2/Makefile b/trunk/arch/arm/mach-omap2/Makefile index 06326a6e460d..bd76394ccaf8 100644 --- a/trunk/arch/arm/mach-omap2/Makefile +++ b/trunk/arch/arm/mach-omap2/Makefile @@ -17,9 +17,7 @@ obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common) obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common) -ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),) -obj-y += mcbsp.o -endif +obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_TWL4030_CORE) += omap_twl.o diff --git a/trunk/arch/arm/mach-omap2/board-omap4panda.c b/trunk/arch/arm/mach-omap2/board-omap4panda.c index e4415917693f..1af564b0487e 100644 --- a/trunk/arch/arm/mach-omap2/board-omap4panda.c +++ b/trunk/arch/arm/mach-omap2/board-omap4panda.c @@ -530,7 +530,7 @@ void omap4_panda_display_init(void) static void omap4_panda_init_rev(void) { - if (cpu_is_omap443x()) { + if (cpu_is_omap4430()) { /* PandaBoard 4430 */ /* ASoC audio configuration */ panda_abe_audio_data.card_name = "PandaBoard"; diff --git a/trunk/arch/arm/mach-omap2/devices.c b/trunk/arch/arm/mach-omap2/devices.c index e9fae652cd04..283d11eae693 100644 --- a/trunk/arch/arm/mach-omap2/devices.c +++ b/trunk/arch/arm/mach-omap2/devices.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -303,8 +304,29 @@ static struct platform_device omap_pcm = { .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); } diff --git a/trunk/arch/arm/mach-omap2/mcbsp.c b/trunk/arch/arm/mach-omap2/mcbsp.c index ecc039e794db..fb4bcf81a183 100644 --- a/trunk/arch/arm/mach-omap2/mcbsp.c +++ b/trunk/arch/arm/mach-omap2/mcbsp.c @@ -34,7 +34,7 @@ #include "cm2xxx_3xxx.h" #include "cm-regbits-34xx.h" -/* McBSP1 internal signal muxing function for OMAP2/3 */ +/* McBSP internal signal muxing function */ static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, const char *src) { @@ -65,42 +65,6 @@ static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, return 0; } -/* McBSP4 internal signal muxing function for OMAP4 */ -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31) -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30) -static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - /* - * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR - * mux) is used */ - v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else if (!strcmp(src, "clkx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else if (!strcmp(src, "fsx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - return 0; -} - /* McBSP CLKS source switching function */ static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk, const char *src) @@ -182,15 +146,9 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->has_ccr = true; } pdata->set_clk_src = omap2_mcbsp_set_clk_src; - - /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ - if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) + if (id == 1) pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; - /* On OMAP4 the McBSP4 port has 6 pin configuration */ - if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; - if (oh->class->rev == MCBSP_CONFIG_TYPE3) { if (id == 2) /* The FIFO has 1024 + 256 locations */ @@ -222,6 +180,7 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) name, oh->name); return PTR_ERR(pdev); } + omap_mcbsp_count++; return 0; } @@ -229,6 +188,11 @@ static int __init omap2_mcbsp_init(void) { omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); - return 0; + mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), + GFP_KERNEL); + if (!mcbsp_ptr) + return -ENOMEM; + + return omap_mcbsp_init(); } arch_initcall(omap2_mcbsp_init); diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index 8f81503a4df7..aa59f4247dc5 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -110,6 +110,14 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. +config OMAP_MCBSP + bool "McBSP support" + depends on ARCH_OMAP + default y + help + Say Y here if you want support for the OMAP Multichannel + Buffered Serial Port. + config OMAP_MBOX_FWK tristate "Mailbox framework support" depends on ARCH_OMAP diff --git a/trunk/arch/arm/plat-omap/Makefile b/trunk/arch/arm/plat-omap/Makefile index c0fe2757b695..9a584614e7e6 100644 --- a/trunk/arch/arm/plat-omap/Makefile +++ b/trunk/arch/arm/plat-omap/Makefile @@ -17,6 +17,8 @@ obj-$(CONFIG_ARCH_OMAP2) += omap_device.o obj-$(CONFIG_ARCH_OMAP3) += omap_device.o obj-$(CONFIG_ARCH_OMAP4) += omap_device.o +obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o + obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o diff --git a/trunk/arch/arm/plat-omap/include/plat/mcbsp.h b/trunk/arch/arm/plat-omap/include/plat/mcbsp.h index 18814127809a..8fa74e2c9d6e 100644 --- a/trunk/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/trunk/arch/arm/plat-omap/include/plat/mcbsp.h @@ -27,10 +27,271 @@ #include #include +/* 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 = port_nr - 1, \ +} + #define MCBSP_CONFIG_TYPE2 0x2 #define MCBSP_CONFIG_TYPE3 0x3 #define MCBSP_CONFIG_TYPE4 0x4 +/* McBSP register numbers. Register address offset = num * reg_step */ +enum { + /* Common registers */ + OMAP_MCBSP_REG_SPCR2 = 4, + OMAP_MCBSP_REG_SPCR1, + OMAP_MCBSP_REG_RCR2, + OMAP_MCBSP_REG_RCR1, + OMAP_MCBSP_REG_XCR2, + OMAP_MCBSP_REG_XCR1, + OMAP_MCBSP_REG_SRGR2, + OMAP_MCBSP_REG_SRGR1, + OMAP_MCBSP_REG_MCR2, + OMAP_MCBSP_REG_MCR1, + OMAP_MCBSP_REG_RCERA, + OMAP_MCBSP_REG_RCERB, + OMAP_MCBSP_REG_XCERA, + OMAP_MCBSP_REG_XCERB, + OMAP_MCBSP_REG_PCR0, + OMAP_MCBSP_REG_RCERC, + OMAP_MCBSP_REG_RCERD, + OMAP_MCBSP_REG_XCERC, + OMAP_MCBSP_REG_XCERD, + OMAP_MCBSP_REG_RCERE, + OMAP_MCBSP_REG_RCERF, + OMAP_MCBSP_REG_XCERE, + OMAP_MCBSP_REG_XCERF, + OMAP_MCBSP_REG_RCERG, + OMAP_MCBSP_REG_RCERH, + OMAP_MCBSP_REG_XCERG, + OMAP_MCBSP_REG_XCERH, + + /* OMAP1-OMAP2420 registers */ + OMAP_MCBSP_REG_DRR2 = 0, + OMAP_MCBSP_REG_DRR1, + OMAP_MCBSP_REG_DXR2, + OMAP_MCBSP_REG_DXR1, + + /* OMAP2430 and onwards */ + OMAP_MCBSP_REG_DRR = 0, + OMAP_MCBSP_REG_DXR = 2, + OMAP_MCBSP_REG_SYSCON = 35, + OMAP_MCBSP_REG_THRSH2, + OMAP_MCBSP_REG_THRSH1, + OMAP_MCBSP_REG_IRQST = 40, + OMAP_MCBSP_REG_IRQEN, + OMAP_MCBSP_REG_WAKEUPEN, + OMAP_MCBSP_REG_XCCR, + OMAP_MCBSP_REG_RCCR, + OMAP_MCBSP_REG_XBUFFSTAT, + OMAP_MCBSP_REG_RBUFFSTAT, + OMAP_MCBSP_REG_SSELCR, +}; + +/* OMAP3 sidetone control registers */ +#define OMAP_ST_REG_REV 0x00 +#define OMAP_ST_REG_SYSCONFIG 0x10 +#define OMAP_ST_REG_IRQSTATUS 0x18 +#define OMAP_ST_REG_IRQENABLE 0x1C +#define OMAP_ST_REG_SGAINCR 0x24 +#define OMAP_ST_REG_SFIRCR 0x28 +#define OMAP_ST_REG_SSELCR 0x2C + +/************************** McBSP SPCR1 bit definitions ***********************/ +#define RRST 0x0001 +#define RRDY 0x0002 +#define RFULL 0x0004 +#define RSYNC_ERR 0x0008 +#define RINTM(value) ((value)<<4) /* bits 4:5 */ +#define ABIS 0x0040 +#define DXENA 0x0080 +#define CLKSTP(value) ((value)<<11) /* bits 11:12 */ +#define RJUST(value) ((value)<<13) /* bits 13:14 */ +#define ALB 0x8000 +#define DLB 0x8000 + +/************************** McBSP SPCR2 bit definitions ***********************/ +#define XRST 0x0001 +#define XRDY 0x0002 +#define XEMPTY 0x0004 +#define XSYNC_ERR 0x0008 +#define XINTM(value) ((value)<<4) /* bits 4:5 */ +#define GRST 0x0040 +#define FRST 0x0080 +#define SOFT 0x0100 +#define FREE 0x0200 + +/************************** McBSP PCR bit definitions *************************/ +#define CLKRP 0x0001 +#define CLKXP 0x0002 +#define FSRP 0x0004 +#define FSXP 0x0008 +#define DR_STAT 0x0010 +#define DX_STAT 0x0020 +#define CLKS_STAT 0x0040 +#define SCLKME 0x0080 +#define CLKRM 0x0100 +#define CLKXM 0x0200 +#define FSRM 0x0400 +#define FSXM 0x0800 +#define RIOEN 0x1000 +#define XIOEN 0x2000 +#define IDLE_EN 0x4000 + +/************************** McBSP RCR1 bit definitions ************************/ +#define RWDLEN1(value) ((value)<<5) /* Bits 5:7 */ +#define RFRLEN1(value) ((value)<<8) /* Bits 8:14 */ + +/************************** McBSP XCR1 bit definitions ************************/ +#define XWDLEN1(value) ((value)<<5) /* Bits 5:7 */ +#define XFRLEN1(value) ((value)<<8) /* Bits 8:14 */ + +/*************************** McBSP RCR2 bit definitions ***********************/ +#define RDATDLY(value) (value) /* Bits 0:1 */ +#define RFIG 0x0004 +#define RCOMPAND(value) ((value)<<3) /* Bits 3:4 */ +#define RWDLEN2(value) ((value)<<5) /* Bits 5:7 */ +#define RFRLEN2(value) ((value)<<8) /* Bits 8:14 */ +#define RPHASE 0x8000 + +/*************************** McBSP XCR2 bit definitions ***********************/ +#define XDATDLY(value) (value) /* Bits 0:1 */ +#define XFIG 0x0004 +#define XCOMPAND(value) ((value)<<3) /* Bits 3:4 */ +#define XWDLEN2(value) ((value)<<5) /* Bits 5:7 */ +#define XFRLEN2(value) ((value)<<8) /* Bits 8:14 */ +#define XPHASE 0x8000 + +/************************* McBSP SRGR1 bit definitions ************************/ +#define CLKGDV(value) (value) /* Bits 0:7 */ +#define FWID(value) ((value)<<8) /* Bits 8:15 */ + +/************************* McBSP SRGR2 bit definitions ************************/ +#define FPER(value) (value) /* Bits 0:11 */ +#define FSGM 0x1000 +#define CLKSM 0x2000 +#define CLKSP 0x4000 +#define GSYNC 0x8000 + +/************************* McBSP MCR1 bit definitions *************************/ +#define RMCM 0x0001 +#define RCBLK(value) ((value)<<2) /* Bits 2:4 */ +#define RPABLK(value) ((value)<<5) /* Bits 5:6 */ +#define RPBBLK(value) ((value)<<7) /* Bits 7:8 */ + +/************************* McBSP MCR2 bit definitions *************************/ +#define XMCM(value) (value) /* Bits 0:1 */ +#define XCBLK(value) ((value)<<2) /* Bits 2:4 */ +#define XPABLK(value) ((value)<<5) /* Bits 5:6 */ +#define XPBBLK(value) ((value)<<7) /* Bits 7:8 */ + +/*********************** McBSP XCCR bit definitions *************************/ +#define EXTCLKGATE 0x8000 +#define PPCONNECT 0x4000 +#define DXENDLY(value) ((value)<<12) /* Bits 12:13 */ +#define XFULL_CYCLE 0x0800 +#define DILB 0x0020 +#define XDMAEN 0x0008 +#define XDISABLE 0x0001 + +/********************** McBSP RCCR bit definitions *************************/ +#define RFULL_CYCLE 0x0800 +#define RDMAEN 0x0008 +#define RDISABLE 0x0001 + +/********************** McBSP SYSCONFIG bit definitions ********************/ +#define CLOCKACTIVITY(value) ((value)<<8) +#define SIDLEMODE(value) ((value)<<3) +#define ENAWAKEUP 0x0004 +#define SOFTRST 0x0002 + +/********************** McBSP SSELCR bit definitions ***********************/ +#define SIDETONEEN 0x0400 + +/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/ +#define ST_AUTOIDLE 0x0001 + +/********************** McBSP Sidetone SGAINCR bit definitions *************/ +#define ST_CH1GAIN(value) ((value<<16)) /* Bits 16:31 */ +#define ST_CH0GAIN(value) (value) /* Bits 0:15 */ + +/********************** McBSP Sidetone SFIRCR bit definitions **************/ +#define ST_FIRCOEFF(value) (value) /* Bits 0:15 */ + +/********************** McBSP Sidetone SSELCR bit definitions **************/ +#define ST_COEFFWRDONE 0x0004 +#define ST_COEFFWREN 0x0002 +#define ST_SIDETONEEN 0x0001 + +/********************** McBSP DMA operating modes **************************/ +#define MCBSP_DMA_MODE_ELEMENT 0 +#define MCBSP_DMA_MODE_THRESHOLD 1 +#define MCBSP_DMA_MODE_FRAME 2 + +/********************** McBSP WAKEUPEN bit definitions *********************/ +#define XEMPTYEOFEN 0x4000 +#define XRDYEN 0x0400 +#define XEOFEN 0x0200 +#define XFSXEN 0x0100 +#define XSYNCERREN 0x0080 +#define RRDYEN 0x0008 +#define REOFEN 0x0004 +#define RFSREN 0x0002 +#define RSYNCERREN 0x0001 + +/* CLKR signal muxing options */ +#define CLKR_SRC_CLKR 0 +#define CLKR_SRC_CLKX 1 + +/* FSR signal muxing options */ +#define FSR_SRC_FSR 0 +#define FSR_SRC_FSX 1 + +/* McBSP functional clock sources */ +#define MCBSP_CLKS_PRCM_SRC 0 +#define MCBSP_CLKS_PAD_SRC 1 + +/* we don't do multichannel for now */ +struct omap_mcbsp_reg_cfg { + u16 spcr2; + u16 spcr1; + u16 rcr2; + u16 rcr1; + u16 xcr2; + u16 xcr1; + u16 srgr2; + u16 srgr1; + u16 mcr2; + u16 mcr1; + u16 pcr0; + u16 rcerc; + u16 rcerd; + u16 xcerc; + u16 xcerd; + u16 rcere; + u16 rcerf; + u16 xcere; + u16 xcerf; + u16 rcerg; + u16 rcerh; + u16 xcerg; + u16 xcerh; + u16 xccr; + u16 rccr; +}; + +typedef enum { + OMAP_MCBSP_WORD_8 = 0, + OMAP_MCBSP_WORD_12, + OMAP_MCBSP_WORD_16, + OMAP_MCBSP_WORD_20, + OMAP_MCBSP_WORD_24, + OMAP_MCBSP_WORD_32, +} omap_mcbsp_word_length; + /* Platform specific configuration */ struct omap_mcbsp_ops { void (*request)(unsigned int); @@ -51,6 +312,43 @@ struct omap_mcbsp_platform_data { int (*mux_signal)(struct device *dev, const char *signal, const char *src); }; +struct omap_mcbsp_st_data { + void __iomem *io_base_st; + bool running; + bool enabled; + s16 taps[128]; /* Sidetone filter coefficients */ + int nr_taps; /* Number of filter coefficients in use */ + s16 ch0gain; + s16 ch1gain; +}; + +struct omap_mcbsp { + struct device *dev; + unsigned long phys_base; + unsigned long phys_dma_base; + void __iomem *io_base; + u8 id; + u8 free; + + int rx_irq; + int tx_irq; + + /* DMA stuff */ + u8 dma_rx_sync; + u8 dma_tx_sync; + + /* Protect the field .free, while checking if the mcbsp is in use */ + spinlock_t lock; + struct omap_mcbsp_platform_data *pdata; + struct clk *fclk; + struct omap_mcbsp_st_data *st_data; + int dma_op_mode; + u16 max_tx_thres; + u16 max_rx_thres; + void *reg_cache; + int reg_cache_size; +}; + /** * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod * @sidetone: name of the sidetone device @@ -59,4 +357,39 @@ struct omap_mcbsp_dev_attr { const char *sidetone; }; +extern struct omap_mcbsp **mcbsp_ptr; +extern int omap_mcbsp_count; + +int omap_mcbsp_init(void); +void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); +void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); +void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); +u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); +u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); +u16 omap_mcbsp_get_fifo_size(unsigned int id); +u16 omap_mcbsp_get_tx_delay(unsigned int id); +u16 omap_mcbsp_get_rx_delay(unsigned int id); +int omap_mcbsp_get_dma_op_mode(unsigned int id); +int omap_mcbsp_request(unsigned int id); +void omap_mcbsp_free(unsigned int id); +void omap_mcbsp_start(unsigned int id, int tx, int rx); +void omap_mcbsp_stop(unsigned int id, int tx, int rx); + +/* McBSP functional clock source changing function */ +extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id); + +/* McBSP signal muxing API */ +void omap2_mcbsp1_mux_clkr_src(u8 mux); +void omap2_mcbsp1_mux_fsr_src(u8 mux); + +int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream); +int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream); + +/* Sidetone specific API */ +int omap_st_set_chgain(unsigned int id, int channel, s16 chgain); +int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain); +int omap_st_enable(unsigned int id); +int omap_st_disable(unsigned int id); +int omap_st_is_enabled(unsigned int id); + #endif diff --git a/trunk/sound/soc/omap/mcbsp.c b/trunk/arch/arm/plat-omap/mcbsp.c similarity index 66% rename from trunk/sound/soc/omap/mcbsp.c rename to trunk/arch/arm/plat-omap/mcbsp.c index e5f44440d1b9..4b15cd7926d7 100644 --- a/trunk/sound/soc/omap/mcbsp.c +++ b/trunk/arch/arm/plat-omap/mcbsp.c @@ -1,11 +1,9 @@ /* - * sound/soc/omap/mcbsp.c + * linux/arch/arm/plat-omap/mcbsp.c * * Copyright (C) 2004 Nokia Corporation * Author: Samuel Ortiz * - * Contact: Jarkko Nikula - * Peter Ujfalusi * * 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 @@ -26,8 +24,13 @@ #include #include +#include -#include "mcbsp.h" +struct omap_mcbsp **mcbsp_ptr; +int omap_mcbsp_count; + +#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) +#define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) { @@ -77,8 +80,10 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) #define MCBSP_ST_WRITE(mcbsp, reg, val) \ omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) -static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp) +static void omap_mcbsp_dump_reg(u8 id) { + struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); + dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", MCBSP_READ(mcbsp, DRR2)); @@ -151,9 +156,16 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) * You either call this function or set the McBSP registers * by yourself before calling omap_mcbsp_start(). */ -void omap_mcbsp_config(struct omap_mcbsp *mcbsp, - const struct omap_mcbsp_reg_cfg *config) +void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) { + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); + dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", mcbsp->id, mcbsp->phys_base); @@ -173,10 +185,33 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp, MCBSP_WRITE(mcbsp, XCCR, config->xccr); MCBSP_WRITE(mcbsp, RCCR, config->rccr); } - /* Enable wakeup behavior */ - if (mcbsp->pdata->has_wakeup) - MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); } +EXPORT_SYMBOL(omap_mcbsp_config); + +/** + * omap_mcbsp_dma_params - returns the dma channel number + * @id - mcbsp id + * @stream - indicates the direction of data flow (rx or tx) + * + * Returns the dma channel number for the rx channel or tx channel + * based on the value of @stream for the requested mcbsp given by @id + */ +int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream) +{ + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + if (stream) + return mcbsp->dma_rx_sync; + else + return mcbsp->dma_tx_sync; +} +EXPORT_SYMBOL(omap_mcbsp_dma_ch_params); /** * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register @@ -187,11 +222,17 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp, * to be used by DMA for transferring/receiving data based on the value of * @stream for the requested mcbsp given by @id */ -static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp, - unsigned int stream) +int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream) { + struct omap_mcbsp *mcbsp; int data_reg; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + if (mcbsp->pdata->reg_size == 2) { if (stream) data_reg = OMAP_MCBSP_REG_DRR1; @@ -206,6 +247,7 @@ static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp, return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step; } +EXPORT_SYMBOL(omap_mcbsp_dma_reg_params); static void omap_st_on(struct omap_mcbsp *mcbsp) { @@ -274,11 +316,20 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp) ST_CH1GAIN(st_data->ch1gain)); } -int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain) +int omap_st_set_chgain(unsigned int id, int channel, s16 chgain) { - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; int ret = 0; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + if (!st_data) return -ENOENT; @@ -296,12 +347,22 @@ int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain) return ret; } +EXPORT_SYMBOL(omap_st_set_chgain); -int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain) +int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain) { - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; int ret = 0; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + if (!st_data) return -ENOENT; @@ -316,12 +377,13 @@ int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain) return ret; } +EXPORT_SYMBOL(omap_st_get_chgain); static int omap_st_start(struct omap_mcbsp *mcbsp) { struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - if (st_data->enabled && !st_data->running) { + if (st_data && st_data->enabled && !st_data->running) { omap_st_fir_write(mcbsp, st_data->taps); omap_st_chgain(mcbsp); @@ -334,9 +396,18 @@ static int omap_st_start(struct omap_mcbsp *mcbsp) return 0; } -int omap_st_enable(struct omap_mcbsp *mcbsp) +int omap_st_enable(unsigned int id) { - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; if (!st_data) return -ENODEV; @@ -348,12 +419,13 @@ int omap_st_enable(struct omap_mcbsp *mcbsp) return 0; } +EXPORT_SYMBOL(omap_st_enable); static int omap_st_stop(struct omap_mcbsp *mcbsp) { struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - if (st_data->running) { + if (st_data && st_data->running) { if (!mcbsp->free) { omap_st_off(mcbsp); st_data->running = 0; @@ -363,11 +435,20 @@ static int omap_st_stop(struct omap_mcbsp *mcbsp) return 0; } -int omap_st_disable(struct omap_mcbsp *mcbsp) +int omap_st_disable(unsigned int id) { - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; int ret = 0; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; + if (!st_data) return -ENODEV; @@ -378,52 +459,136 @@ int omap_st_disable(struct omap_mcbsp *mcbsp) return ret; } +EXPORT_SYMBOL(omap_st_disable); -int omap_st_is_enabled(struct omap_mcbsp *mcbsp) +int omap_st_is_enabled(unsigned int id) { - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + struct omap_mcbsp *mcbsp; + struct omap_mcbsp_st_data *st_data; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + + mcbsp = id_to_mcbsp_ptr(id); + st_data = mcbsp->st_data; if (!st_data) return -ENODEV; + return st_data->enabled; } +EXPORT_SYMBOL(omap_st_is_enabled); /* * omap_mcbsp_set_rx_threshold configures the transmit threshold in words. * The threshold parameter is 1 based, and it is converted (threshold - 1) * for the THRSH2 register. */ -void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold) +void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) { + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); if (mcbsp->pdata->buffer_size == 0) return; if (threshold && threshold <= mcbsp->max_tx_thres) MCBSP_WRITE(mcbsp, THRSH2, threshold - 1); } +EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); /* * omap_mcbsp_set_rx_threshold configures the receive threshold in words. * The threshold parameter is 1 based, and it is converted (threshold - 1) * for the THRSH1 register. */ -void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold) +void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) { + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); if (mcbsp->pdata->buffer_size == 0) return; if (threshold && threshold <= mcbsp->max_rx_thres) MCBSP_WRITE(mcbsp, THRSH1, threshold - 1); } +EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); + +/* + * omap_mcbsp_get_max_tx_thres just return the current configured + * maximum threshold for transmission + */ +u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + return mcbsp->max_tx_thres; +} +EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold); + +/* + * omap_mcbsp_get_max_rx_thres just return the current configured + * maximum threshold for reception + */ +u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + return mcbsp->max_rx_thres; +} +EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); + +u16 omap_mcbsp_get_fifo_size(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + return mcbsp->pdata->buffer_size; +} +EXPORT_SYMBOL(omap_mcbsp_get_fifo_size); /* * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO */ -u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp) +u16 omap_mcbsp_get_tx_delay(unsigned int id) { + struct omap_mcbsp *mcbsp; u16 buffstat; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); if (mcbsp->pdata->buffer_size == 0) return 0; @@ -433,15 +598,22 @@ u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp) /* Number of slots are different in McBSP ports */ return mcbsp->pdata->buffer_size - buffstat; } +EXPORT_SYMBOL(omap_mcbsp_get_tx_delay); /* * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO * to reach the threshold value (when the DMA will be triggered to read it) */ -u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp) +u16 omap_mcbsp_get_rx_delay(unsigned int id) { + struct omap_mcbsp *mcbsp; u16 buffstat, threshold; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); if (mcbsp->pdata->buffer_size == 0) return 0; @@ -456,12 +628,41 @@ u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp) else return threshold - buffstat; } +EXPORT_SYMBOL(omap_mcbsp_get_rx_delay); + +/* + * omap_mcbsp_get_dma_op_mode just return the current configured + * operating mode for the mcbsp channel + */ +int omap_mcbsp_get_dma_op_mode(unsigned int id) +{ + struct omap_mcbsp *mcbsp; + int dma_op_mode; + + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + + dma_op_mode = mcbsp->dma_op_mode; + + return dma_op_mode; +} +EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); -int omap_mcbsp_request(struct omap_mcbsp *mcbsp) +int omap_mcbsp_request(unsigned int id) { + struct omap_mcbsp *mcbsp; void *reg_cache; int err; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return -ENODEV; + } + mcbsp = id_to_mcbsp_ptr(id); + reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL); if (!reg_cache) { return -ENOMEM; @@ -480,7 +681,13 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp) spin_unlock(&mcbsp->lock); if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) - mcbsp->pdata->ops->request(mcbsp->id - 1); + mcbsp->pdata->ops->request(id); + + pm_runtime_get_sync(mcbsp->dev); + + /* Enable wakeup behavior */ + if (mcbsp->pdata->has_wakeup) + MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); /* * Make sure that transmitter, receiver and sample-rate generator are @@ -515,12 +722,14 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp) free_irq(mcbsp->tx_irq, (void *)mcbsp); err_clk_disable: if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id - 1); + mcbsp->pdata->ops->free(id); /* Disable wakeup behavior */ if (mcbsp->pdata->has_wakeup) MCBSP_WRITE(mcbsp, WAKEUPEN, 0); + pm_runtime_put_sync(mcbsp->dev); + spin_lock(&mcbsp->lock); mcbsp->free = true; mcbsp->reg_cache = NULL; @@ -530,34 +739,34 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp) return err; } +EXPORT_SYMBOL(omap_mcbsp_request); -void omap_mcbsp_free(struct omap_mcbsp *mcbsp) +void omap_mcbsp_free(unsigned int id) { + struct omap_mcbsp *mcbsp; void *reg_cache; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); + if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id - 1); + mcbsp->pdata->ops->free(id); /* Disable wakeup behavior */ if (mcbsp->pdata->has_wakeup) MCBSP_WRITE(mcbsp, WAKEUPEN, 0); + pm_runtime_put_sync(mcbsp->dev); + if (mcbsp->rx_irq) free_irq(mcbsp->rx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp); reg_cache = mcbsp->reg_cache; - /* - * Select CLKS source from internal source unconditionally before - * marking the McBSP port as free. - * If the external clock source via MCBSP_CLKS pin has been selected the - * system will refuse to enter idle if the CLKS pin source is not reset - * back to internal source. - */ - if (!cpu_class_is_omap1()) - omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); - spin_lock(&mcbsp->lock); if (mcbsp->free) dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); @@ -569,17 +778,25 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp) if (reg_cache) kfree(reg_cache); } +EXPORT_SYMBOL(omap_mcbsp_free); /* * Here we start the McBSP, by enabling transmitter, receiver or both. * If no transmitter or receiver is active prior calling, then sample-rate * generator and frame sync are started. */ -void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx) +void omap_mcbsp_start(unsigned int id, int tx, int rx) { + struct omap_mcbsp *mcbsp; int enable_srg = 0; u16 w; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + mcbsp = id_to_mcbsp_ptr(id); + if (mcbsp->st_data) omap_st_start(mcbsp); @@ -629,14 +846,23 @@ void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx) } /* Dump McBSP Regs */ - omap_mcbsp_dump_reg(mcbsp); + omap_mcbsp_dump_reg(id); } +EXPORT_SYMBOL(omap_mcbsp_start); -void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) +void omap_mcbsp_stop(unsigned int id, int tx, int rx) { + struct omap_mcbsp *mcbsp; int idle; u16 w; + if (!omap_mcbsp_check_valid_id(id)) { + printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); + return; + } + + mcbsp = id_to_mcbsp_ptr(id); + /* Reset transmitter */ tx &= 1; if (mcbsp->pdata->has_ccr) { @@ -669,11 +895,19 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) if (mcbsp->st_data) omap_st_stop(mcbsp); } +EXPORT_SYMBOL(omap_mcbsp_stop); -int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) +int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) { + struct omap_mcbsp *mcbsp; const char *src; + if (!omap_mcbsp_check_valid_id(id)) { + pr_err("%s: Invalid id (%d)\n", __func__, id + 1); + return -EINVAL; + } + mcbsp = id_to_mcbsp_ptr(id); + if (fck_src_id == MCBSP_CLKS_PAD_SRC) src = "clks_ext"; else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) @@ -686,37 +920,43 @@ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) else return -EINVAL; } +EXPORT_SYMBOL(omap2_mcbsp_set_clks_src); -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) +void omap2_mcbsp1_mux_clkr_src(u8 mux) { - const char *signal, *src; - - if (mcbsp->pdata->mux_signal) - return -EINVAL; + struct omap_mcbsp *mcbsp; + const char *src; - switch (mux) { - case CLKR_SRC_CLKR: - signal = "clkr"; + if (mux == CLKR_SRC_CLKR) src = "clkr"; - break; - case CLKR_SRC_CLKX: - signal = "clkr"; + else if (mux == CLKR_SRC_CLKX) src = "clkx"; - break; - case FSR_SRC_FSR: - signal = "fsr"; + else + return; + + mcbsp = id_to_mcbsp_ptr(0); + if (mcbsp->pdata->mux_signal) + mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src); +} +EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src); + +void omap2_mcbsp1_mux_fsr_src(u8 mux) +{ + struct omap_mcbsp *mcbsp; + const char *src; + + if (mux == FSR_SRC_FSR) src = "fsr"; - break; - case FSR_SRC_FSX: - signal = "fsr"; + else if (mux == FSR_SRC_FSX) src = "fsx"; - break; - default: - return -EINVAL; - } + else + return; - return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); + mcbsp = id_to_mcbsp_ptr(0); + if (mcbsp->pdata->mux_signal) + mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src); } +EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src); #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) @@ -892,56 +1132,97 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp, struct omap_mcbsp_st_data *st_data; int err; - st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL); - if (!st_data) - return -ENOMEM; + st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL); + if (!st_data) { + err = -ENOMEM; + goto err1; + } - st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start, - resource_size(res)); - if (!st_data->io_base_st) - return -ENOMEM; + st_data->io_base_st = ioremap(res->start, resource_size(res)); + if (!st_data->io_base_st) { + err = -ENOMEM; + goto err2; + } err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group); if (err) - return err; + goto err3; mcbsp->st_data = st_data; return 0; + +err3: + iounmap(st_data->io_base_st); +err2: + kfree(st_data); +err1: + return err; + +} + +static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp) +{ + struct omap_mcbsp_st_data *st_data = mcbsp->st_data; + + sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); + iounmap(st_data->io_base_st); + kfree(st_data); } /* * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. */ -int __devinit omap_mcbsp_init(struct platform_device *pdev) +static int __devinit omap_mcbsp_probe(struct platform_device *pdev) { - struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); + struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; + struct omap_mcbsp *mcbsp; + int id = pdev->id - 1; struct resource *res; int ret = 0; + if (!pdata) { + dev_err(&pdev->dev, "McBSP device initialized without" + "platform data\n"); + ret = -EINVAL; + goto exit; + } + + dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); + + if (id >= omap_mcbsp_count) { + dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); + ret = -EINVAL; + goto exit; + } + + mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL); + if (!mcbsp) { + ret = -ENOMEM; + goto exit; + } + spin_lock_init(&mcbsp->lock); + mcbsp->id = id + 1; mcbsp->free = true; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (!res) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - dev_err(mcbsp->dev, "invalid memory resource\n"); - return -ENOMEM; + dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory" + "resource\n", __func__, pdev->id); + ret = -ENOMEM; + goto exit; } } - if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), - dev_name(&pdev->dev))) { - dev_err(mcbsp->dev, "memory region already claimed\n"); - return -ENODEV; - } - mcbsp->phys_base = res->start; mcbsp->reg_cache_size = resource_size(res); - mcbsp->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!mcbsp->io_base) - return -ENOMEM; + mcbsp->io_base = ioremap(res->start, resource_size(res)); + if (!mcbsp->io_base) { + ret = -ENOMEM; + goto err_ioremap; + } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); if (!res) @@ -953,38 +1234,40 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev) mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); /* From OMAP4 there will be a single irq line */ - if (mcbsp->tx_irq == -ENXIO) { + if (mcbsp->tx_irq == -ENXIO) mcbsp->tx_irq = platform_get_irq(pdev, 0); - mcbsp->rx_irq = 0; - } res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); if (!res) { - dev_err(&pdev->dev, "invalid rx DMA channel\n"); - return -ENODEV; + dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n", + __func__, pdev->id); + ret = -ENODEV; + goto err_res; } - /* RX DMA request number, and port address configuration */ - mcbsp->dma_data[1].name = "Audio Capture"; - mcbsp->dma_data[1].dma_req = res->start; - mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); + mcbsp->dma_rx_sync = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); if (!res) { - dev_err(&pdev->dev, "invalid tx DMA channel\n"); - return -ENODEV; + dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n", + __func__, pdev->id); + ret = -ENODEV; + goto err_res; } - /* TX DMA request number, and port address configuration */ - mcbsp->dma_data[0].name = "Audio Playback"; - mcbsp->dma_data[0].dma_req = res->start; - mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); + mcbsp->dma_tx_sync = res->start; mcbsp->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(mcbsp->fclk)) { ret = PTR_ERR(mcbsp->fclk); - dev_err(mcbsp->dev, "unable to get fck: %d\n", ret); - return ret; + dev_err(&pdev->dev, "unable to get fck: %d\n", ret); + goto err_res; } + mcbsp->pdata = pdata; + mcbsp->dev = &pdev->dev; + mcbsp_ptr[id] = mcbsp; + platform_set_drvdata(pdev, mcbsp); + pm_runtime_enable(mcbsp->dev); + mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; if (mcbsp->pdata->buffer_size) { /* @@ -1024,17 +1307,55 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev) err_st: if (mcbsp->pdata->buffer_size) - sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group); + sysfs_remove_group(&mcbsp->dev->kobj, + &additional_attr_group); err_thres: clk_put(mcbsp->fclk); +err_res: + iounmap(mcbsp->io_base); +err_ioremap: + kfree(mcbsp); +exit: return ret; } -void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp) +static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { - if (mcbsp->pdata->buffer_size) - sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group); + struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - if (mcbsp->st_data) - sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); + platform_set_drvdata(pdev, NULL); + if (mcbsp) { + + if (mcbsp->pdata && mcbsp->pdata->ops && + mcbsp->pdata->ops->free) + mcbsp->pdata->ops->free(mcbsp->id); + + if (mcbsp->pdata->buffer_size) + sysfs_remove_group(&mcbsp->dev->kobj, + &additional_attr_group); + + if (mcbsp->st_data) + omap_st_remove(mcbsp); + + clk_put(mcbsp->fclk); + + iounmap(mcbsp->io_base); + kfree(mcbsp); + } + + return 0; +} + +static struct platform_driver omap_mcbsp_driver = { + .probe = omap_mcbsp_probe, + .remove = __devexit_p(omap_mcbsp_remove), + .driver = { + .name = "omap-mcbsp", + }, +}; + +int __init omap_mcbsp_init(void) +{ + /* Register the McBSP driver */ + return platform_driver_register(&omap_mcbsp_driver); } diff --git a/trunk/sound/soc/omap/Kconfig b/trunk/sound/soc/omap/Kconfig index e00dd0b1139c..47b23fea20c2 100644 --- a/trunk/sound/soc/omap/Kconfig +++ b/trunk/sound/soc/omap/Kconfig @@ -7,6 +7,7 @@ config SND_OMAP_SOC_DMIC config SND_OMAP_SOC_MCBSP tristate + select OMAP_MCBSP config SND_OMAP_SOC_MCPDM tristate @@ -26,6 +27,7 @@ config SND_OMAP_SOC_N810 config SND_OMAP_SOC_RX51 tristate "SoC Audio support for Nokia RX-51" depends on SND_OMAP_SOC && MACH_NOKIA_RX51 + select OMAP_MCBSP select SND_OMAP_SOC_MCBSP select SND_SOC_TLV320AIC3X select SND_SOC_TPA6130A2 diff --git a/trunk/sound/soc/omap/Makefile b/trunk/sound/soc/omap/Makefile index 1d656bce01d4..123ac18303e5 100644 --- a/trunk/sound/soc/omap/Makefile +++ b/trunk/sound/soc/omap/Makefile @@ -1,7 +1,7 @@ # OMAP Platform Support snd-soc-omap-objs := omap-pcm.o snd-soc-omap-dmic-objs := omap-dmic.o -snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o +snd-soc-omap-mcbsp-objs := omap-mcbsp.o snd-soc-omap-mcpdm-objs := omap-mcpdm.o snd-soc-omap-hdmi-objs := omap-hdmi.o diff --git a/trunk/sound/soc/omap/am3517evm.c b/trunk/sound/soc/omap/am3517evm.c index 009533ab8d18..add4866d7e67 100644 --- a/trunk/sound/soc/omap/am3517evm.c +++ b/trunk/sound/soc/omap/am3517evm.c @@ -95,7 +95,7 @@ static const struct snd_soc_dapm_route audio_map[] = { static struct snd_soc_dai_link am3517evm_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai_name = "omap-mcbsp.1", + .cpu_dai_name ="omap-mcbsp-dai.0", .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic23-codec.2-001a", diff --git a/trunk/sound/soc/omap/ams-delta.c b/trunk/sound/soc/omap/ams-delta.c index 49fe63ce51f7..78563bbbbf01 100644 --- a/trunk/sound/soc/omap/ams-delta.c +++ b/trunk/sound/soc/omap/ams-delta.c @@ -584,7 +584,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link ams_delta_dai_link = { .name = "CX20442", .stream_name = "CX20442", - .cpu_dai_name = "omap-mcbsp.1", + .cpu_dai_name ="omap-mcbsp-dai.0", .codec_dai_name = "cx20442-voice", .init = ams_delta_cx20442_init, .platform_name = "omap-pcm-audio", diff --git a/trunk/sound/soc/omap/igep0020.c b/trunk/sound/soc/omap/igep0020.c index e8357819175b..ccae58a1339c 100644 --- a/trunk/sound/soc/omap/igep0020.c +++ b/trunk/sound/soc/omap/igep0020.c @@ -60,7 +60,7 @@ static struct snd_soc_ops igep2_ops = { static struct snd_soc_dai_link igep2_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/mcbsp.h b/trunk/sound/soc/omap/mcbsp.h deleted file mode 100644 index a944fcc9073c..000000000000 --- a/trunk/sound/soc/omap/mcbsp.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * sound/soc/omap/mcbsp.h - * - * OMAP Multi-Channel Buffered Serial Port - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * 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 __ASOC_MCBSP_H -#define __ASOC_MCBSP_H - -#include "omap-pcm.h" - -/* McBSP register numbers. Register address offset = num * reg_step */ -enum { - /* Common registers */ - OMAP_MCBSP_REG_SPCR2 = 4, - OMAP_MCBSP_REG_SPCR1, - OMAP_MCBSP_REG_RCR2, - OMAP_MCBSP_REG_RCR1, - OMAP_MCBSP_REG_XCR2, - OMAP_MCBSP_REG_XCR1, - OMAP_MCBSP_REG_SRGR2, - OMAP_MCBSP_REG_SRGR1, - OMAP_MCBSP_REG_MCR2, - OMAP_MCBSP_REG_MCR1, - OMAP_MCBSP_REG_RCERA, - OMAP_MCBSP_REG_RCERB, - OMAP_MCBSP_REG_XCERA, - OMAP_MCBSP_REG_XCERB, - OMAP_MCBSP_REG_PCR0, - OMAP_MCBSP_REG_RCERC, - OMAP_MCBSP_REG_RCERD, - OMAP_MCBSP_REG_XCERC, - OMAP_MCBSP_REG_XCERD, - OMAP_MCBSP_REG_RCERE, - OMAP_MCBSP_REG_RCERF, - OMAP_MCBSP_REG_XCERE, - OMAP_MCBSP_REG_XCERF, - OMAP_MCBSP_REG_RCERG, - OMAP_MCBSP_REG_RCERH, - OMAP_MCBSP_REG_XCERG, - OMAP_MCBSP_REG_XCERH, - - /* OMAP1-OMAP2420 registers */ - OMAP_MCBSP_REG_DRR2 = 0, - OMAP_MCBSP_REG_DRR1, - OMAP_MCBSP_REG_DXR2, - OMAP_MCBSP_REG_DXR1, - - /* OMAP2430 and onwards */ - OMAP_MCBSP_REG_DRR = 0, - OMAP_MCBSP_REG_DXR = 2, - OMAP_MCBSP_REG_SYSCON = 35, - OMAP_MCBSP_REG_THRSH2, - OMAP_MCBSP_REG_THRSH1, - OMAP_MCBSP_REG_IRQST = 40, - OMAP_MCBSP_REG_IRQEN, - OMAP_MCBSP_REG_WAKEUPEN, - OMAP_MCBSP_REG_XCCR, - OMAP_MCBSP_REG_RCCR, - OMAP_MCBSP_REG_XBUFFSTAT, - OMAP_MCBSP_REG_RBUFFSTAT, - OMAP_MCBSP_REG_SSELCR, -}; - -/* OMAP3 sidetone control registers */ -#define OMAP_ST_REG_REV 0x00 -#define OMAP_ST_REG_SYSCONFIG 0x10 -#define OMAP_ST_REG_IRQSTATUS 0x18 -#define OMAP_ST_REG_IRQENABLE 0x1C -#define OMAP_ST_REG_SGAINCR 0x24 -#define OMAP_ST_REG_SFIRCR 0x28 -#define OMAP_ST_REG_SSELCR 0x2C - -/************************** McBSP SPCR1 bit definitions ***********************/ -#define RRST BIT(0) -#define RRDY BIT(1) -#define RFULL BIT(2) -#define RSYNC_ERR BIT(3) -#define RINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */ -#define ABIS BIT(6) -#define DXENA BIT(7) -#define CLKSTP(value) (((value) & 0x3) << 11) /* bits 11:12 */ -#define RJUST(value) (((value) & 0x3) << 13) /* bits 13:14 */ -#define ALB BIT(15) -#define DLB BIT(15) - -/************************** McBSP SPCR2 bit definitions ***********************/ -#define XRST BIT(0) -#define XRDY BIT(1) -#define XEMPTY BIT(2) -#define XSYNC_ERR BIT(3) -#define XINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */ -#define GRST BIT(6) -#define FRST BIT(7) -#define SOFT BIT(8) -#define FREE BIT(9) - -/************************** McBSP PCR bit definitions *************************/ -#define CLKRP BIT(0) -#define CLKXP BIT(1) -#define FSRP BIT(2) -#define FSXP BIT(3) -#define DR_STAT BIT(4) -#define DX_STAT BIT(5) -#define CLKS_STAT BIT(6) -#define SCLKME BIT(7) -#define CLKRM BIT(8) -#define CLKXM BIT(9) -#define FSRM BIT(10) -#define FSXM BIT(11) -#define RIOEN BIT(12) -#define XIOEN BIT(13) -#define IDLE_EN BIT(14) - -/************************** McBSP RCR1 bit definitions ************************/ -#define RWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define RFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ - -/************************** McBSP XCR1 bit definitions ************************/ -#define XWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define XFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ - -/*************************** McBSP RCR2 bit definitions ***********************/ -#define RDATDLY(value) ((value) & 0x3) /* Bits 0:1 */ -#define RFIG BIT(2) -#define RCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */ -#define RWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define RFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ -#define RPHASE BIT(15) - -/*************************** McBSP XCR2 bit definitions ***********************/ -#define XDATDLY(value) ((value) & 0x3) /* Bits 0:1 */ -#define XFIG BIT(2) -#define XCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */ -#define XWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define XFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ -#define XPHASE BIT(15) - -/************************* McBSP SRGR1 bit definitions ************************/ -#define CLKGDV(value) ((value) & 0x7f) /* Bits 0:7 */ -#define FWID(value) (((value) & 0xff) << 8) /* Bits 8:15 */ - -/************************* McBSP SRGR2 bit definitions ************************/ -#define FPER(value) ((value) & 0x0fff) /* Bits 0:11 */ -#define FSGM BIT(12) -#define CLKSM BIT(13) -#define CLKSP BIT(14) -#define GSYNC BIT(15) - -/************************* McBSP MCR1 bit definitions *************************/ -#define RMCM BIT(0) -#define RCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */ -#define RPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */ -#define RPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */ - -/************************* McBSP MCR2 bit definitions *************************/ -#define XMCM(value) ((value) & 0x3) /* Bits 0:1 */ -#define XCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */ -#define XPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */ -#define XPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */ - -/*********************** McBSP XCCR bit definitions *************************/ -#define XDISABLE BIT(0) -#define XDMAEN BIT(3) -#define DILB BIT(5) -#define XFULL_CYCLE BIT(11) -#define DXENDLY(value) (((value) & 0x3) << 12) /* Bits 12:13 */ -#define PPCONNECT BIT(14) -#define EXTCLKGATE BIT(15) - -/********************** McBSP RCCR bit definitions *************************/ -#define RDISABLE BIT(0) -#define RDMAEN BIT(3) -#define RFULL_CYCLE BIT(11) - -/********************** McBSP SYSCONFIG bit definitions ********************/ -#define SOFTRST BIT(1) -#define ENAWAKEUP BIT(2) -#define SIDLEMODE(value) (((value) & 0x3) << 3) -#define CLOCKACTIVITY(value) (((value) & 0x3) << 8) - -/********************** McBSP SSELCR bit definitions ***********************/ -#define SIDETONEEN BIT(10) - -/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/ -#define ST_AUTOIDLE BIT(0) - -/********************** McBSP Sidetone SGAINCR bit definitions *************/ -#define ST_CH0GAIN(value) ((value) & 0xffff) /* Bits 0:15 */ -#define ST_CH1GAIN(value) (((value) & 0xffff) << 16) /* Bits 16:31 */ - -/********************** McBSP Sidetone SFIRCR bit definitions **************/ -#define ST_FIRCOEFF(value) ((value) & 0xffff) /* Bits 0:15 */ - -/********************** McBSP Sidetone SSELCR bit definitions **************/ -#define ST_SIDETONEEN BIT(0) -#define ST_COEFFWREN BIT(1) -#define ST_COEFFWRDONE BIT(2) - -/********************** McBSP DMA operating modes **************************/ -#define MCBSP_DMA_MODE_ELEMENT 0 -#define MCBSP_DMA_MODE_THRESHOLD 1 -#define MCBSP_DMA_MODE_FRAME 2 - -/********************** McBSP WAKEUPEN bit definitions *********************/ -#define RSYNCERREN BIT(0) -#define RFSREN BIT(1) -#define REOFEN BIT(2) -#define RRDYEN BIT(3) -#define XSYNCERREN BIT(7) -#define XFSXEN BIT(8) -#define XEOFEN BIT(9) -#define XRDYEN BIT(10) -#define XEMPTYEOFEN BIT(14) - -/* Clock signal muxing options */ -#define CLKR_SRC_CLKR 0 /* CLKR signal is from the CLKR pin */ -#define CLKR_SRC_CLKX 1 /* CLKR signal is from the CLKX pin */ -#define FSR_SRC_FSR 2 /* FSR signal is from the FSR pin */ -#define FSR_SRC_FSX 3 /* FSR signal is from the FSX pin */ - -/* McBSP functional clock sources */ -#define MCBSP_CLKS_PRCM_SRC 0 -#define MCBSP_CLKS_PAD_SRC 1 - -/* we don't do multichannel for now */ -struct omap_mcbsp_reg_cfg { - u16 spcr2; - u16 spcr1; - u16 rcr2; - u16 rcr1; - u16 xcr2; - u16 xcr1; - u16 srgr2; - u16 srgr1; - u16 mcr2; - u16 mcr1; - u16 pcr0; - u16 rcerc; - u16 rcerd; - u16 xcerc; - u16 xcerd; - u16 rcere; - u16 rcerf; - u16 xcere; - u16 xcerf; - u16 rcerg; - u16 rcerh; - u16 xcerg; - u16 xcerh; - u16 xccr; - u16 rccr; -}; - -struct omap_mcbsp_st_data { - void __iomem *io_base_st; - bool running; - bool enabled; - s16 taps[128]; /* Sidetone filter coefficients */ - int nr_taps; /* Number of filter coefficients in use */ - s16 ch0gain; - s16 ch1gain; -}; - -struct omap_mcbsp { - struct device *dev; - struct clk *fclk; - spinlock_t lock; - unsigned long phys_base; - unsigned long phys_dma_base; - void __iomem *io_base; - u8 id; - /* - * Flags indicating is the bus already activated and configured by - * another substream - */ - int active; - int configured; - u8 free; - - int rx_irq; - int tx_irq; - - /* Protect the field .free, while checking if the mcbsp is in use */ - struct omap_mcbsp_platform_data *pdata; - struct omap_mcbsp_st_data *st_data; - struct omap_mcbsp_reg_cfg cfg_regs; - struct omap_pcm_dma_data dma_data[2]; - int dma_op_mode; - u16 max_tx_thres; - u16 max_rx_thres; - void *reg_cache; - int reg_cache_size; - - unsigned int fmt; - unsigned int in_freq; - int clk_div; - int wlen; -}; - -void omap_mcbsp_config(struct omap_mcbsp *mcbsp, - const struct omap_mcbsp_reg_cfg *config); -void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold); -void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold); -u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp); -u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp); -int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp); -int omap_mcbsp_request(struct omap_mcbsp *mcbsp); -void omap_mcbsp_free(struct omap_mcbsp *mcbsp); -void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx); -void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); - -/* McBSP functional clock source changing function */ -int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); - -/* McBSP signal muxing API */ -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); - -/* Sidetone specific API */ -int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); -int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); -int omap_st_enable(struct omap_mcbsp *mcbsp); -int omap_st_disable(struct omap_mcbsp *mcbsp); -int omap_st_is_enabled(struct omap_mcbsp *mcbsp); - -int __devinit omap_mcbsp_init(struct platform_device *pdev); -void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp); - -#endif /* __ASOC_MCBSP_H */ diff --git a/trunk/sound/soc/omap/n810.c b/trunk/sound/soc/omap/n810.c index abac4b690750..c292bf0fd19c 100644 --- a/trunk/sound/soc/omap/n810.c +++ b/trunk/sound/soc/omap/n810.c @@ -275,7 +275,7 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link n810_dai = { .name = "TLV320AIC33", .stream_name = "AIC33", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic3x-codec.2-0018", .codec_dai_name = "tlv320aic3x-hifi", diff --git a/trunk/sound/soc/omap/omap-mcbsp.c b/trunk/sound/soc/omap/omap-mcbsp.c index 6912ac7cb625..1287b870f221 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.c +++ b/trunk/sound/soc/omap/omap-mcbsp.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -34,7 +33,6 @@ #include #include -#include "mcbsp.h" #include "omap-mcbsp.h" #include "omap-pcm.h" @@ -48,31 +46,42 @@ .private_value = (unsigned long) &(struct soc_mixer_control) \ {.min = xmin, .max = xmax} } -enum { - OMAP_MCBSP_WORD_8 = 0, - OMAP_MCBSP_WORD_12, - OMAP_MCBSP_WORD_16, - OMAP_MCBSP_WORD_20, - OMAP_MCBSP_WORD_24, - OMAP_MCBSP_WORD_32, +struct omap_mcbsp_data { + unsigned int bus_id; + struct omap_mcbsp_reg_cfg regs; + unsigned int fmt; + /* + * Flags indicating is the bus already activated and configured by + * another substream + */ + int active; + int configured; + unsigned int in_freq; + int clk_div; + int wlen; }; +static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; + /* * Stream DMA parameters. DMA request line and port address are set runtime * since they are different between OMAP1 and later OMAPs */ +static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2]; + static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_pcm_dma_data *dma_data; + int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); int words; dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) + if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) /* * Configure McBSP threshold based on either: * packet_size, when the sDMA is in packet mode, or @@ -82,15 +91,15 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) words = dma_data->packet_size; else words = snd_pcm_lib_period_bytes(substream) / - (mcbsp->wlen / 8); + (mcbsp_data->wlen / 8); else words = 1; /* Configure McBSP internal buffer usage */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - omap_mcbsp_set_tx_threshold(mcbsp, words); + omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words); else - omap_mcbsp_set_rx_threshold(mcbsp, words); + omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words); } static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, @@ -100,12 +109,12 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct omap_mcbsp *mcbsp = rule->private; + struct omap_mcbsp_data *mcbsp_data = rule->private; struct snd_interval frames; int size; snd_interval_any(&frames); - size = mcbsp->pdata->buffer_size; + size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id); frames.min = size / channels->min; frames.integer = 1; @@ -115,11 +124,12 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); + int bus_id = mcbsp_data->bus_id; int err = 0; if (!cpu_dai->active) - err = omap_mcbsp_request(mcbsp); + err = omap_mcbsp_request(bus_id); /* * OMAP3 McBSP FIFO is word structured. @@ -136,16 +146,16 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) */ - if (mcbsp->pdata->buffer_size) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { /* * Rule for the buffer size. We should not allow * smaller buffer than the FIFO size to avoid underruns */ snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + SNDRV_PCM_HW_PARAM_CHANNELS, omap_mcbsp_hwrule_min_buffersize, - mcbsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); + mcbsp_data, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); /* Make sure, that the period size is always even */ snd_pcm_hw_constraint_step(substream->runtime, 0, @@ -158,33 +168,33 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); if (!cpu_dai->active) { - omap_mcbsp_free(mcbsp); - mcbsp->configured = 0; + omap_mcbsp_free(mcbsp_data->bus_id); + mcbsp_data->configured = 0; } } static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - mcbsp->active++; - omap_mcbsp_start(mcbsp, play, !play); + mcbsp_data->active++; + omap_mcbsp_start(mcbsp_data->bus_id, play, !play); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - omap_mcbsp_stop(mcbsp, play, !play); - mcbsp->active--; + omap_mcbsp_stop(mcbsp_data->bus_id, play, !play); + mcbsp_data->active--; break; default: err = -EINVAL; @@ -199,14 +209,14 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay( { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); u16 fifo_use; snd_pcm_sframes_t delay; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_use = omap_mcbsp_get_tx_delay(mcbsp); + fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id); else - fifo_use = omap_mcbsp_get_rx_delay(mcbsp); + fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id); /* * Divide the used locations with the channel count to get the @@ -222,14 +232,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; struct omap_pcm_dma_data *dma_data; + int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; + unsigned long port; unsigned int format, div, framesize, master; - dma_data = &mcbsp->dma_data[substream->stream]; + dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; + + dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream); + port = omap_mcbsp_dma_reg_params(bus_id, substream->stream); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -243,17 +258,20 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } - if (mcbsp->pdata->buffer_size) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { + if (omap_mcbsp_get_dma_op_mode(bus_id) == + MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - max_thrsh = mcbsp->max_tx_thres; + max_thrsh = omap_mcbsp_get_max_tx_threshold( + mcbsp_data->bus_id); else - max_thrsh = mcbsp->max_rx_thres; + max_thrsh = omap_mcbsp_get_max_rx_threshold( + mcbsp_data->bus_id); /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: @@ -286,12 +304,15 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } } + dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; + dma_data->dma_req = dma; + dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); - if (mcbsp->configured) { + if (mcbsp_data->configured) { /* McBSP already configured by another stream */ return 0; } @@ -300,7 +321,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); - format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK; + format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { @@ -338,10 +359,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ - master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK; + master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { - div = mcbsp->clk_div ? mcbsp->clk_div : 1; - framesize = (mcbsp->in_freq / div) / params_rate(params); + div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; + framesize = (mcbsp_data->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " @@ -367,9 +388,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, break; } - omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs); - mcbsp->wlen = wlen; - mcbsp->configured = 1; + omap_mcbsp_config(bus_id, &mcbsp_data->regs); + mcbsp_data->wlen = wlen; + mcbsp_data->configured = 1; return 0; } @@ -381,14 +402,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; bool inv_fs = false; - if (mcbsp->configured) + if (mcbsp_data->configured) return 0; - mcbsp->fmt = fmt; + mcbsp_data->fmt = fmt; memset(regs, 0, sizeof(*regs)); /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; @@ -483,13 +504,13 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; if (div_id != OMAP_MCBSP_CLKGDV) return -ENODEV; - mcbsp->clk_div = div; + mcbsp_data->clk_div = div; regs->srgr1 &= ~CLKGDV(0xff); regs->srgr1 |= CLKGDV(div - 1); @@ -500,32 +521,28 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; + struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); + struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int err = 0; - if (mcbsp->active) { - if (freq == mcbsp->in_freq) + if (mcbsp_data->active) { + if (freq == mcbsp_data->in_freq) return 0; else return -EBUSY; } - if (clk_id == OMAP_MCBSP_SYSCLK_CLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { - mcbsp->in_freq = freq; - regs->srgr2 &= ~CLKSM; - regs->pcr0 &= ~SCLKME; - } else if (cpu_class_is_omap1()) { - /* - * McBSP CLKR/FSR signal muxing functions are only available on - * OMAP2 or newer versions - */ - return -EINVAL; - } + /* The McBSP signal muxing functions are only available on McBSP1 */ + if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR || + clk_id == OMAP_MCBSP_CLKR_SRC_CLKX || + clk_id == OMAP_MCBSP_FSR_SRC_FSR || + clk_id == OMAP_MCBSP_FSR_SRC_FSX) + if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0) + return -EINVAL; + + mcbsp_data->in_freq = freq; + regs->srgr2 &= ~CLKSM; + regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: @@ -536,7 +553,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, err = -EINVAL; break; } - err = omap2_mcbsp_set_clks_src(mcbsp, + err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id, MCBSP_CLKS_PRCM_SRC); break; case OMAP_MCBSP_SYSCLK_CLKS_EXT: @@ -544,7 +561,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, err = 0; break; } - err = omap2_mcbsp_set_clks_src(mcbsp, + err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id, MCBSP_CLKS_PAD_SRC); break; @@ -556,16 +573,24 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_CLKR_SRC_CLKR: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); + if (cpu_class_is_omap1()) + break; + omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR); break; case OMAP_MCBSP_CLKR_SRC_CLKX: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); + if (cpu_class_is_omap1()) + break; + omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX); break; case OMAP_MCBSP_FSR_SRC_FSR: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); + if (cpu_class_is_omap1()) + break; + omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR); break; case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); + if (cpu_class_is_omap1()) + break; + omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX); break; default: err = -ENODEV; @@ -585,27 +610,15 @@ static const struct snd_soc_dai_ops mcbsp_dai_ops = { .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, }; -static int omap_mcbsp_probe(struct snd_soc_dai *dai) +static int mcbsp_dai_probe(struct snd_soc_dai *dai) { - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai); - - pm_runtime_enable(mcbsp->dev); - - return 0; -} - -static int omap_mcbsp_remove(struct snd_soc_dai *dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai); - - pm_runtime_disable(mcbsp->dev); - + mcbsp_data[dai->id].bus_id = dai->id; + snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id); return 0; } static struct snd_soc_dai_driver omap_mcbsp_dai = { - .probe = omap_mcbsp_probe, - .remove = omap_mcbsp_remove, + .probe = mcbsp_dai_probe, .playback = { .channels_min = 1, .channels_max = 16, @@ -636,13 +649,11 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, return 0; } -#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ +#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ static int \ -omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \ struct soc_mixer_control *mc = \ (struct soc_mixer_control *)kc->private_value; \ int max = mc->max; \ @@ -653,44 +664,46 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ return -EINVAL; \ \ /* OMAP McBSP implementation uses index values 0..4 */ \ - return omap_st_set_chgain(mcbsp, channel, val); \ + return omap_st_set_chgain((id)-1, channel, val); \ } -#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ +#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ static int \ -omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ +omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ struct snd_ctl_elem_value *uc) \ { \ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \ s16 chgain; \ \ - if (omap_st_get_chgain(mcbsp, channel, &chgain)) \ + if (omap_st_get_chgain((id)-1, channel, &chgain)) \ return -EAGAIN; \ \ uc->value.integer.value[0] = chgain; \ return 0; \ } -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; u8 value = ucontrol->value.integer.value[0]; - if (value == omap_st_is_enabled(mcbsp)) + if (value == omap_st_is_enabled(mc->reg)) return 0; if (value) - omap_st_enable(mcbsp); + omap_st_enable(mc->reg); else - omap_st_disable(mcbsp); + omap_st_disable(mc->reg); return 1; } @@ -698,10 +711,10 @@ static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; - ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp); + ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); return 0; } @@ -710,12 +723,12 @@ static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), + omap_mcbsp2_get_st_ch0_volume, + omap_mcbsp2_set_st_ch0_volume), OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), + omap_mcbsp2_get_st_ch1_volume, + omap_mcbsp2_set_st_ch1_volume), }; static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { @@ -723,30 +736,25 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), + omap_mcbsp3_get_st_ch0_volume, + omap_mcbsp3_set_st_ch0_volume), OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), + omap_mcbsp3_get_st_ch1_volume, + omap_mcbsp3_set_st_ch1_volume), }; -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) +int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai) { - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - - if (!mcbsp->st_data) + if (!cpu_is_omap34xx()) return -ENODEV; - switch (cpu_dai->id) { - case 2: /* McBSP 2 */ - return snd_soc_add_dai_controls(cpu_dai, - omap_mcbsp2_st_controls, + switch (dai->id) { + case 1: /* McBSP 2 */ + return snd_soc_add_dai_controls(dai, omap_mcbsp2_st_controls, ARRAY_SIZE(omap_mcbsp2_st_controls)); - case 3: /* McBSP 3 */ - return snd_soc_add_dai_controls(cpu_dai, - omap_mcbsp3_st_controls, + case 2: /* McBSP 3 */ + return snd_soc_add_dai_controls(dai, omap_mcbsp3_st_controls, ARRAY_SIZE(omap_mcbsp3_st_controls)); default: break; @@ -758,51 +766,18 @@ EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) { - struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct omap_mcbsp *mcbsp; - int ret; - - if (!pdata) { - dev_err(&pdev->dev, "missing platform data.\n"); - return -EINVAL; - } - mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL); - if (!mcbsp) - return -ENOMEM; - - mcbsp->id = pdev->id; - mcbsp->pdata = pdata; - mcbsp->dev = &pdev->dev; - platform_set_drvdata(pdev, mcbsp); - - ret = omap_mcbsp_init(pdev); - if (!ret) - return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); - - return ret; + return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); } static int __devexit asoc_mcbsp_remove(struct platform_device *pdev) { - struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - snd_soc_unregister_dai(&pdev->dev); - - if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id); - - omap_mcbsp_sysfs_remove(mcbsp); - - clk_put(mcbsp->fclk); - - platform_set_drvdata(pdev, NULL); - return 0; } static struct platform_driver asoc_mcbsp_driver = { .driver = { - .name = "omap-mcbsp", + .name = "omap-mcbsp-dai", .owner = THIS_MODULE, }, diff --git a/trunk/sound/soc/omap/omap-mcbsp.h b/trunk/sound/soc/omap/omap-mcbsp.h index f877b16f19c9..476fe2add703 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.h +++ b/trunk/sound/soc/omap/omap-mcbsp.h @@ -59,6 +59,6 @@ enum omap_mcbsp_div { #define NUM_LINKS 5 #endif -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); +int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai); #endif diff --git a/trunk/sound/soc/omap/omap-pcm.h b/trunk/sound/soc/omap/omap-pcm.h index b92248cbd47a..f95fe3064172 100644 --- a/trunk/sound/soc/omap/omap-pcm.h +++ b/trunk/sound/soc/omap/omap-pcm.h @@ -25,8 +25,6 @@ #ifndef __OMAP_PCM_H__ #define __OMAP_PCM_H__ -struct snd_pcm_substream; - struct omap_pcm_dma_data { char *name; /* stream identifier */ int dma_req; /* DMA request line */ diff --git a/trunk/sound/soc/omap/omap3beagle.c b/trunk/sound/soc/omap/omap3beagle.c index 2830dfd05661..3357dcc47ed4 100644 --- a/trunk/sound/soc/omap/omap3beagle.c +++ b/trunk/sound/soc/omap/omap3beagle.c @@ -91,7 +91,7 @@ static struct snd_soc_ops omap3beagle_ops = { static struct snd_soc_dai_link omap3beagle_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .platform_name = "omap-pcm-audio", .codec_dai_name = "twl4030-hifi", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/omap3evm.c b/trunk/sound/soc/omap/omap3evm.c index 3d468c9179d7..071fcb09b8b2 100644 --- a/trunk/sound/soc/omap/omap3evm.c +++ b/trunk/sound/soc/omap/omap3evm.c @@ -58,7 +58,7 @@ static struct snd_soc_ops omap3evm_ops = { static struct snd_soc_dai_link omap3evm_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/omap3pandora.c b/trunk/sound/soc/omap/omap3pandora.c index 4c3a0978578a..07794bd10952 100644 --- a/trunk/sound/soc/omap/omap3pandora.c +++ b/trunk/sound/soc/omap/omap3pandora.c @@ -208,7 +208,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { { .name = "PCM1773", .stream_name = "HiFi Out", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", @@ -219,7 +219,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { }, { .name = "TWL4030", .stream_name = "Line/Mic In", - .cpu_dai_name = "omap-mcbsp.4", + .cpu_dai_name = "omap-mcbsp-dai.3", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/osk5912.c b/trunk/sound/soc/omap/osk5912.c index b1a9d64cbc56..d859b597e7ec 100644 --- a/trunk/sound/soc/omap/osk5912.c +++ b/trunk/sound/soc/omap/osk5912.c @@ -96,7 +96,7 @@ static const struct snd_soc_dapm_route audio_map[] = { static struct snd_soc_dai_link osk_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", - .cpu_dai_name = "omap-mcbsp.1", + .cpu_dai_name = "omap-mcbsp-dai.0", .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic23-codec", diff --git a/trunk/sound/soc/omap/overo.c b/trunk/sound/soc/omap/overo.c index 6ac3e0c3c282..2ee889c50256 100644 --- a/trunk/sound/soc/omap/overo.c +++ b/trunk/sound/soc/omap/overo.c @@ -60,7 +60,7 @@ static struct snd_soc_ops overo_ops = { static struct snd_soc_dai_link overo_dai = { .name = "TWL4030", .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/rx51.c b/trunk/sound/soc/omap/rx51.c index 2712dd232b6d..58936c730a87 100644 --- a/trunk/sound/soc/omap/rx51.c +++ b/trunk/sound/soc/omap/rx51.c @@ -313,7 +313,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) return err; snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42); - err = omap_mcbsp_st_add_controls(rtd); + err = omap_mcbsp_st_add_controls(rtd->cpu_dai); if (err < 0) return err; @@ -353,7 +353,7 @@ static struct snd_soc_dai_link rx51_dai[] = { { .name = "TLV320AIC34", .stream_name = "AIC34", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "tlv320aic3x-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic3x-codec.2-0018", diff --git a/trunk/sound/soc/omap/sdp3430.c b/trunk/sound/soc/omap/sdp3430.c index 0e283226e2bf..2c850662ea7e 100644 --- a/trunk/sound/soc/omap/sdp3430.c +++ b/trunk/sound/soc/omap/sdp3430.c @@ -187,7 +187,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = { { .name = "TWL4030 I2S", .stream_name = "TWL4030 Audio", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", @@ -199,7 +199,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = { { .name = "TWL4030 PCM", .stream_name = "TWL4030 Voice", - .cpu_dai_name = "omap-mcbsp.3", + .cpu_dai_name = "omap-mcbsp-dai.2", .codec_dai_name = "twl4030-voice", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/omap/zoom2.c b/trunk/sound/soc/omap/zoom2.c index 920e0d9e03db..981616d61f67 100644 --- a/trunk/sound/soc/omap/zoom2.c +++ b/trunk/sound/soc/omap/zoom2.c @@ -131,7 +131,7 @@ static struct snd_soc_dai_link zoom2_dai[] = { { .name = "TWL4030 I2S", .stream_name = "TWL4030 Audio", - .cpu_dai_name = "omap-mcbsp.2", + .cpu_dai_name = "omap-mcbsp-dai.1", .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", @@ -143,7 +143,7 @@ static struct snd_soc_dai_link zoom2_dai[] = { { .name = "TWL4030 PCM", .stream_name = "TWL4030 Voice", - .cpu_dai_name = "omap-mcbsp.3", + .cpu_dai_name = "omap-mcbsp-dai.2", .codec_dai_name = "twl4030-voice", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index a4d4aa1e6c49..dcd11609f930 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -1667,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); if (!dapm->debugfs_dapm) { - printk(KERN_WARNING + dev_warn(dapm->dev, "Failed to create DAPM debugfs directory\n"); return; }