From: Shawn Guo Date: Mon, 5 Mar 2012 14:30:53 +0000 (+0800) Subject: ASoC: imx: move audmux driver into sound/soc/imx X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=3c77c29c49c6213c55ad8dacc687817b3568c0ce;p=openwrt%2Fstaging%2Fblogic.git ASoC: imx: move audmux driver into sound/soc/imx As audmux becomes a platform driver and its callers are all ASoC machine drivers, there is no reason to keep it in arch folder, so move it to sound/soc/imx. One bonus point would be those ASoC machine drivers stop including mach/audmux.h, since it's been moved to sound/soc/imx/imx-audmux.h. This should be a move to the right direction in terms of single kernel image goal. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer Signed-off-by: Mark Brown --- diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 495a8543e71e..3919fba52ac8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -46,7 +46,6 @@ config SOC_IMX21 bool select MACH_MX21 select CPU_ARM926T - select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -55,7 +54,6 @@ config SOC_IMX25 bool select ARCH_MX25 select CPU_ARM926T - select ARCH_MXC_AUDMUX select ARCH_MXC_IOMUX_V3 select MXC_AVIC @@ -63,7 +61,6 @@ config SOC_IMX27 bool select MACH_MX27 select CPU_ARM926T - select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -72,7 +69,6 @@ config SOC_IMX31 bool select CPU_V6 select IMX_HAVE_PLATFORM_MXC_RNGA - select ARCH_MXC_AUDMUX select MXC_AVIC select SMP_ON_UP if SMP @@ -80,7 +76,6 @@ config SOC_IMX35 bool select CPU_V6 select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX select HAVE_EPIT select MXC_AVIC select SMP_ON_UP if SMP @@ -89,7 +84,6 @@ config SOC_IMX5 select CPU_V7 select MXC_TZIC select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX select ARCH_HAS_CPUFREQ select ARCH_MX5 bool diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c index d817fc80b986..aaa592fdb9ce 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "devices-imx51.h" diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 0461d16e5ca6..c722f9ce6918 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -88,9 +88,6 @@ config IMX_HAVE_IOMUX_V1 config ARCH_MXC_IOMUX_V3 bool -config ARCH_MXC_AUDMUX - bool - config IRAM_ALLOC bool select GENERIC_ALLOCATOR diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 530c81dfd9be..e81290c27c65 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o obj-$(CONFIG_MXC_PWM) += pwm.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o -obj-$(CONFIG_ARCH_MXC_AUDMUX) += audmux.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/plat-mxc/audmux.c b/arch/arm/plat-mxc/audmux.c deleted file mode 100644 index a8c9e04771bf..000000000000 --- a/arch/arm/plat-mxc/audmux.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2012 Freescale Semiconductor, Inc. - * Copyright 2012 Linaro Ltd. - * Copyright 2009 Pengutronix, Sascha Hauer - * - * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "imx-audmux" - -static struct clk *audmux_clk; -static void __iomem *audmux_base; - -#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8) -#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) - -#ifdef CONFIG_DEBUG_FS -static struct dentry *audmux_debugfs_root; - -static int audmux_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -/* There is an annoying discontinuity in the SSI numbering with regard - * to the Linux number of the devices */ -static const char *audmux_port_string(int port) -{ - switch (port) { - case MX31_AUDMUX_PORT1_SSI0: - return "imx-ssi.0"; - case MX31_AUDMUX_PORT2_SSI1: - return "imx-ssi.1"; - case MX31_AUDMUX_PORT3_SSI_PINS_3: - return "SSI3"; - case MX31_AUDMUX_PORT4_SSI_PINS_4: - return "SSI4"; - case MX31_AUDMUX_PORT5_SSI_PINS_5: - return "SSI5"; - case MX31_AUDMUX_PORT6_SSI_PINS_6: - return "SSI6"; - default: - return "UNKNOWN"; - } -} - -static ssize_t audmux_read_file(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - int port = (int)file->private_data; - u32 pdcr, ptcr; - - if (!buf) - return -ENOMEM; - - if (audmux_clk) - clk_enable(audmux_clk); - - ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port)); - pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port)); - - if (audmux_clk) - clk_disable(audmux_clk); - - ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", - pdcr, ptcr); - - if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxFS output from %s, ", - audmux_port_string((ptcr >> 27) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxFS input, "); - - if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxClk output from %s", - audmux_port_string((ptcr >> 22) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxClk input"); - - ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); - - if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) { - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "Port is symmetric"); - } else { - if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxFS output from %s, ", - audmux_port_string((ptcr >> 17) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxFS input, "); - - if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxClk output from %s", - audmux_port_string((ptcr >> 12) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxClk input"); - } - - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "\nData received from %s\n", - audmux_port_string((pdcr >> 13) & 0x7)); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); - - kfree(buf); - - return ret; -} - -static const struct file_operations audmux_debugfs_fops = { - .open = audmux_open_file, - .read = audmux_read_file, - .llseek = default_llseek, -}; - -static void __init audmux_debugfs_init(void) -{ - int i; - char buf[20]; - - audmux_debugfs_root = debugfs_create_dir("audmux", NULL); - if (!audmux_debugfs_root) { - pr_warning("Failed to create AUDMUX debugfs root\n"); - return; - } - - for (i = 1; i < 8; i++) { - snprintf(buf, sizeof(buf), "ssi%d", i); - if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, - (void *)i, &audmux_debugfs_fops)) - pr_warning("Failed to create AUDMUX port %d debugfs file\n", - i); - } -} - -static void __exit audmux_debugfs_remove(void) -{ - debugfs_remove_recursive(audmux_debugfs_root); -} -#else -static inline void audmux_debugfs_init(void) -{ -} - -static inline void audmux_debugfs_remove(void) -{ -} -#endif - -enum imx_audmux_type { - IMX21_AUDMUX, - IMX31_AUDMUX, -} audmux_type; - -static struct platform_device_id imx_audmux_ids[] = { - { - .name = "imx21-audmux", - .driver_data = IMX21_AUDMUX, - }, { - .name = "imx31-audmux", - .driver_data = IMX31_AUDMUX, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, imx_audmux_ids); - -static const uint8_t port_mapping[] = { - 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, -}; - -int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) -{ - if (audmux_type != IMX21_AUDMUX) - return -EINVAL; - - if (!audmux_base) - return -ENOSYS; - - if (port >= ARRAY_SIZE(port_mapping)) - return -EINVAL; - - writel(pcr, audmux_base + port_mapping[port]); - - return 0; -} -EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); - -int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, - unsigned int pdcr) -{ - if (audmux_type != IMX31_AUDMUX) - return -EINVAL; - - if (!audmux_base) - return -ENOSYS; - - if (audmux_clk) - clk_enable(audmux_clk); - - writel(ptcr, audmux_base + MXC_AUDMUX_V2_PTCR(port)); - writel(pdcr, audmux_base + MXC_AUDMUX_V2_PDCR(port)); - - if (audmux_clk) - clk_disable(audmux_clk); - - return 0; -} -EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); - -static int __init imx_audmux_probe(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - audmux_base = devm_request_and_ioremap(&pdev->dev, res); - if (!audmux_base) - return -EADDRNOTAVAIL; - - audmux_clk = clk_get(&pdev->dev, "audmux"); - if (IS_ERR(audmux_clk)) { - dev_dbg(&pdev->dev, "cannot get clock: %ld\n", - PTR_ERR(audmux_clk)); - audmux_clk = NULL; - } - - audmux_type = pdev->id_entry->driver_data; - if (audmux_type == IMX31_AUDMUX) - audmux_debugfs_init(); - - return 0; -} - -static int __exit imx_audmux_remove(struct platform_device *pdev) -{ - if (audmux_type == IMX31_AUDMUX) - audmux_debugfs_remove(); - clk_put(audmux_clk); - - return 0; -} - -static struct platform_driver imx_audmux_driver = { - .probe = imx_audmux_probe, - .remove = __exit_p(imx_audmux_remove), - .id_table = imx_audmux_ids, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - } -}; - -static int __init imx_audmux_init(void) -{ - return platform_driver_register(&imx_audmux_driver); -} -subsys_initcall(imx_audmux_init); - -static void __exit imx_audmux_exit(void) -{ - platform_driver_unregister(&imx_audmux_driver); -} -module_exit(imx_audmux_exit); - -MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver"); -MODULE_AUTHOR("Sascha Hauer "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/arch/arm/plat-mxc/include/mach/audmux.h b/arch/arm/plat-mxc/include/mach/audmux.h deleted file mode 100644 index 6fda788ed0e9..000000000000 --- a/arch/arm/plat-mxc/include/mach/audmux.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __MACH_AUDMUX_H -#define __MACH_AUDMUX_H - -#define MX27_AUDMUX_HPCR1_SSI0 0 -#define MX27_AUDMUX_HPCR2_SSI1 1 -#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2 -#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3 -#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4 -#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5 - -#define MX31_AUDMUX_PORT1_SSI0 0 -#define MX31_AUDMUX_PORT2_SSI1 1 -#define MX31_AUDMUX_PORT3_SSI_PINS_3 2 -#define MX31_AUDMUX_PORT4_SSI_PINS_4 3 -#define MX31_AUDMUX_PORT5_SSI_PINS_5 4 -#define MX31_AUDMUX_PORT6_SSI_PINS_6 5 - -#define MX51_AUDMUX_PORT1_SSI0 0 -#define MX51_AUDMUX_PORT2_SSI1 1 -#define MX51_AUDMUX_PORT3 2 -#define MX51_AUDMUX_PORT4 3 -#define MX51_AUDMUX_PORT5 4 -#define MX51_AUDMUX_PORT6 5 -#define MX51_AUDMUX_PORT7 6 - -/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ -#define MXC_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) -#define MXC_AUDMUX_V1_PCR_INMEN (1 << 8) -#define MXC_AUDMUX_V1_PCR_TXRXEN (1 << 10) -#define MXC_AUDMUX_V1_PCR_SYN (1 << 12) -#define MXC_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) -#define MXC_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) -#define MXC_AUDMUX_V1_PCR_RCLKDIR (1 << 24) -#define MXC_AUDMUX_V1_PCR_RFSDIR (1 << 25) -#define MXC_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) -#define MXC_AUDMUX_V1_PCR_TCLKDIR (1 << 30) -#define MXC_AUDMUX_V1_PCR_TFSDIR (1 << 31) - -/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ -#define MXC_AUDMUX_V2_PTCR_TFSDIR (1 << 31) -#define MXC_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) -#define MXC_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) -#define MXC_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) -#define MXC_AUDMUX_V2_PTCR_RFSDIR (1 << 21) -#define MXC_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) -#define MXC_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) -#define MXC_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) -#define MXC_AUDMUX_V2_PTCR_SYN (1 << 11) - -#define MXC_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) -#define MXC_AUDMUX_V2_PDCR_TXRXEN (1 << 12) -#define MXC_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) -#define MXC_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) - -int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr); - -int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, - unsigned int pdcr); - -#endif /* __MACH_AUDMUX_H */ diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index aa4294bf49b2..d3b716663d1d 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -16,11 +16,15 @@ config SND_MXC_SOC_MX2 select SND_SOC_DMAENGINE_PCM tristate +config SND_SOC_IMX_AUDMUX + tristate + config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL select SND_SOC_WM8350 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Enable support for audio on the i.MX31ADS with the WM1133-EV1 PMIC board with WM8835x fitted. @@ -30,6 +34,7 @@ config SND_SOC_MX27VIS_AIC32X4 depends on MACH_IMX27_VISSTRIM_M10 && I2C select SND_SOC_TLV320AIC32X4 select SND_MXC_SOC_MX2 + select SND_SOC_IMX_AUDMUX help Say Y if you want to add support for SoC audio on Visstrim SM10 board with TLV320AIC32X4 codec. @@ -40,6 +45,7 @@ config SND_SOC_PHYCORE_AC97 select SND_SOC_AC97_BUS select SND_SOC_WM9712 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Say Y if you want to add support for SoC audio on Phytec phyCORE and phyCARD boards in AC97 mode @@ -53,6 +59,7 @@ config SND_SOC_EUKREA_TLV320 depends on I2C select SND_SOC_TLV320AIC23 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index d6d609ba7e24..5c40541b8315 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -2,10 +2,12 @@ snd-soc-imx-objs := imx-ssi.o snd-soc-imx-fiq-objs := imx-pcm-fiq.o snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o +snd-soc-imx-audmux-objs := imx-audmux.o obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o +obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index bfcb6d9768b8..b375ed4541f6 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -23,10 +23,10 @@ #include #include #include -#include #include "../codecs/tlv320aic23.h" #include "imx-ssi.h" +#include "imx-audmux.h" #define CODEC_CLOCK 12000000 diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c new file mode 100644 index 000000000000..7b162662fe6b --- /dev/null +++ b/sound/soc/imx/imx-audmux.c @@ -0,0 +1,300 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Linaro Ltd. + * Copyright 2009 Pengutronix, Sascha Hauer + * + * Initial development of this code was funded by + * Phytec Messtechnik GmbH, http://www.phytec.de + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "imx-audmux.h" + +#define DRIVER_NAME "imx-audmux" + +static struct clk *audmux_clk; +static void __iomem *audmux_base; + +#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8) +#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) + +#ifdef CONFIG_DEBUG_FS +static struct dentry *audmux_debugfs_root; + +static int audmux_open_file(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +/* There is an annoying discontinuity in the SSI numbering with regard + * to the Linux number of the devices */ +static const char *audmux_port_string(int port) +{ + switch (port) { + case MX31_AUDMUX_PORT1_SSI0: + return "imx-ssi.0"; + case MX31_AUDMUX_PORT2_SSI1: + return "imx-ssi.1"; + case MX31_AUDMUX_PORT3_SSI_PINS_3: + return "SSI3"; + case MX31_AUDMUX_PORT4_SSI_PINS_4: + return "SSI4"; + case MX31_AUDMUX_PORT5_SSI_PINS_5: + return "SSI5"; + case MX31_AUDMUX_PORT6_SSI_PINS_6: + return "SSI6"; + default: + return "UNKNOWN"; + } +} + +static ssize_t audmux_read_file(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + int port = (int)file->private_data; + u32 pdcr, ptcr; + + if (!buf) + return -ENOMEM; + + if (audmux_clk) + clk_enable(audmux_clk); + + ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port)); + pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port)); + + if (audmux_clk) + clk_disable(audmux_clk); + + ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", + pdcr, ptcr); + + if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR) + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "TxFS output from %s, ", + audmux_port_string((ptcr >> 27) & 0x7)); + else + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "TxFS input, "); + + if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR) + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "TxClk output from %s", + audmux_port_string((ptcr >> 22) & 0x7)); + else + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "TxClk input"); + + ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); + + if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) { + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "Port is symmetric"); + } else { + if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR) + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "RxFS output from %s, ", + audmux_port_string((ptcr >> 17) & 0x7)); + else + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "RxFS input, "); + + if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR) + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "RxClk output from %s", + audmux_port_string((ptcr >> 12) & 0x7)); + else + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "RxClk input"); + } + + ret += snprintf(buf + ret, PAGE_SIZE - ret, + "\nData received from %s\n", + audmux_port_string((pdcr >> 13) & 0x7)); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); + + kfree(buf); + + return ret; +} + +static const struct file_operations audmux_debugfs_fops = { + .open = audmux_open_file, + .read = audmux_read_file, + .llseek = default_llseek, +}; + +static void __init audmux_debugfs_init(void) +{ + int i; + char buf[20]; + + audmux_debugfs_root = debugfs_create_dir("audmux", NULL); + if (!audmux_debugfs_root) { + pr_warning("Failed to create AUDMUX debugfs root\n"); + return; + } + + for (i = 1; i < 8; i++) { + snprintf(buf, sizeof(buf), "ssi%d", i); + if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, + (void *)i, &audmux_debugfs_fops)) + pr_warning("Failed to create AUDMUX port %d debugfs file\n", + i); + } +} + +static void __exit audmux_debugfs_remove(void) +{ + debugfs_remove_recursive(audmux_debugfs_root); +} +#else +static inline void audmux_debugfs_init(void) +{ +} + +static inline void audmux_debugfs_remove(void) +{ +} +#endif + +enum imx_audmux_type { + IMX21_AUDMUX, + IMX31_AUDMUX, +} audmux_type; + +static struct platform_device_id imx_audmux_ids[] = { + { + .name = "imx21-audmux", + .driver_data = IMX21_AUDMUX, + }, { + .name = "imx31-audmux", + .driver_data = IMX31_AUDMUX, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, imx_audmux_ids); + +static const uint8_t port_mapping[] = { + 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, +}; + +int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) +{ + if (audmux_type != IMX21_AUDMUX) + return -EINVAL; + + if (!audmux_base) + return -ENOSYS; + + if (port >= ARRAY_SIZE(port_mapping)) + return -EINVAL; + + writel(pcr, audmux_base + port_mapping[port]); + + return 0; +} +EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); + +int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, + unsigned int pdcr) +{ + if (audmux_type != IMX31_AUDMUX) + return -EINVAL; + + if (!audmux_base) + return -ENOSYS; + + if (audmux_clk) + clk_enable(audmux_clk); + + writel(ptcr, audmux_base + MXC_AUDMUX_V2_PTCR(port)); + writel(pdcr, audmux_base + MXC_AUDMUX_V2_PDCR(port)); + + if (audmux_clk) + clk_disable(audmux_clk); + + return 0; +} +EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); + +static int __init imx_audmux_probe(struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + audmux_base = devm_request_and_ioremap(&pdev->dev, res); + if (!audmux_base) + return -EADDRNOTAVAIL; + + audmux_clk = clk_get(&pdev->dev, "audmux"); + if (IS_ERR(audmux_clk)) { + dev_dbg(&pdev->dev, "cannot get clock: %ld\n", + PTR_ERR(audmux_clk)); + audmux_clk = NULL; + } + + audmux_type = pdev->id_entry->driver_data; + if (audmux_type == IMX31_AUDMUX) + audmux_debugfs_init(); + + return 0; +} + +static int __exit imx_audmux_remove(struct platform_device *pdev) +{ + if (audmux_type == IMX31_AUDMUX) + audmux_debugfs_remove(); + clk_put(audmux_clk); + + return 0; +} + +static struct platform_driver imx_audmux_driver = { + .probe = imx_audmux_probe, + .remove = __exit_p(imx_audmux_remove), + .id_table = imx_audmux_ids, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +static int __init imx_audmux_init(void) +{ + return platform_driver_register(&imx_audmux_driver); +} +subsys_initcall(imx_audmux_init); + +static void __exit imx_audmux_exit(void) +{ + platform_driver_unregister(&imx_audmux_driver); +} +module_exit(imx_audmux_exit); + +MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver"); +MODULE_AUTHOR("Sascha Hauer "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h new file mode 100644 index 000000000000..5136d9483f46 --- /dev/null +++ b/sound/soc/imx/imx-audmux.h @@ -0,0 +1,60 @@ +#ifndef __IMX_AUDMUX_H +#define __IMX_AUDMUX_H + +#define MX27_AUDMUX_HPCR1_SSI0 0 +#define MX27_AUDMUX_HPCR2_SSI1 1 +#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2 +#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3 +#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4 +#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5 + +#define MX31_AUDMUX_PORT1_SSI0 0 +#define MX31_AUDMUX_PORT2_SSI1 1 +#define MX31_AUDMUX_PORT3_SSI_PINS_3 2 +#define MX31_AUDMUX_PORT4_SSI_PINS_4 3 +#define MX31_AUDMUX_PORT5_SSI_PINS_5 4 +#define MX31_AUDMUX_PORT6_SSI_PINS_6 5 + +#define MX51_AUDMUX_PORT1_SSI0 0 +#define MX51_AUDMUX_PORT2_SSI1 1 +#define MX51_AUDMUX_PORT3 2 +#define MX51_AUDMUX_PORT4 3 +#define MX51_AUDMUX_PORT5 4 +#define MX51_AUDMUX_PORT6 5 +#define MX51_AUDMUX_PORT7 6 + +/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ +#define MXC_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) +#define MXC_AUDMUX_V1_PCR_INMEN (1 << 8) +#define MXC_AUDMUX_V1_PCR_TXRXEN (1 << 10) +#define MXC_AUDMUX_V1_PCR_SYN (1 << 12) +#define MXC_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) +#define MXC_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) +#define MXC_AUDMUX_V1_PCR_RCLKDIR (1 << 24) +#define MXC_AUDMUX_V1_PCR_RFSDIR (1 << 25) +#define MXC_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) +#define MXC_AUDMUX_V1_PCR_TCLKDIR (1 << 30) +#define MXC_AUDMUX_V1_PCR_TFSDIR (1 << 31) + +/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ +#define MXC_AUDMUX_V2_PTCR_TFSDIR (1 << 31) +#define MXC_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) +#define MXC_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) +#define MXC_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) +#define MXC_AUDMUX_V2_PTCR_RFSDIR (1 << 21) +#define MXC_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) +#define MXC_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) +#define MXC_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) +#define MXC_AUDMUX_V2_PTCR_SYN (1 << 11) + +#define MXC_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) +#define MXC_AUDMUX_V2_PDCR_TXRXEN (1 << 12) +#define MXC_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) +#define MXC_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) + +int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr); + +int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, + unsigned int pdcr); + +#endif /* __IMX_AUDMUX_H */ diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c index 155899c08c0c..dbfad0f62511 100644 --- a/sound/soc/imx/mx27vis-aic32x4.c +++ b/sound/soc/imx/mx27vis-aic32x4.c @@ -32,11 +32,11 @@ #include #include #include -#include #include #include "../codecs/tlv320aic32x4.h" #include "imx-ssi.h" +#include "imx-audmux.h" #define MX27VIS_AMP_GAIN 0 #define MX27VIS_AMP_MUTE 1 diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index a59692e740b4..7dab077f9c30 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -18,7 +18,8 @@ #include #include #include -#include + +#include "imx-audmux.h" static struct snd_soc_card imx_phycore; diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index 37480c90e997..15056d6a1643 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c @@ -21,10 +21,9 @@ #include #include -#include - #include "imx-ssi.h" #include "../codecs/wm8350.h" +#include "imx-audmux.h" /* There is a silicon mic on the board optionally connected via a solder pad * SP1. Define this to enable it.