ASoC: imx: move audmux driver into sound/soc/imx
authorShawn Guo <shawn.guo@linaro.org>
Mon, 5 Mar 2012 14:30:53 +0000 (22:30 +0800)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 6 Mar 2012 00:03:00 +0000 (00:03 +0000)
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 <shawn.guo@linaro.org>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
14 files changed:
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/Makefile
arch/arm/plat-mxc/audmux.c [deleted file]
arch/arm/plat-mxc/include/mach/audmux.h [deleted file]
sound/soc/imx/Kconfig
sound/soc/imx/Makefile
sound/soc/imx/eukrea-tlv320.c
sound/soc/imx/imx-audmux.c [new file with mode: 0644]
sound/soc/imx/imx-audmux.h [new file with mode: 0644]
sound/soc/imx/mx27vis-aic32x4.c
sound/soc/imx/phycore-ac97.c
sound/soc/imx/wm1133-ev1.c

index 495a8543e71e616c2c7d223bbb28c31ab72551ab..3919fba52ac80c30196eb1abe5bc152b7edd0f0b 100644 (file)
@@ -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
index d817fc80b986c8231da7df66dea5231f6211f4b5..aaa592fdb9ce38b84e70985a9e1496cae0c9496b 100644 (file)
@@ -37,7 +37,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
 
 #include "devices-imx51.h"
 
index 0461d16e5ca636a2f12da3e70ffbdc9113a7d301..c722f9ce691827e8924674119b75708ba7ea6428 100644 (file)
@@ -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
index 530c81dfd9be718dd3e2c0c9aefe17c5f71a46bc..e81290c27c655bdf4ab5f4d58a61ee41cc8013e9 100644 (file)
@@ -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 (file)
index a8c9e04..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
- * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
- *
- * 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 <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <mach/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 <s.hauer@pengutronix.de>");
-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 (file)
index 6fda788..0000000
+++ /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 */
index aa4294bf49b28bac9d26f90522bb5b39fe60cddc..d3b716663d1d5a06f3c477788a77fda25baa5060 100644 (file)
@@ -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
index d6d609ba7e24afa539e0cc9804caee1a43026379..5c40541b831535837a1f800802947ee526450b4c 100644 (file)
@@ -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
index bfcb6d9768b8f69dab5745e9321b802f94bcc1c3..b375ed4541f61c7462951c7b248b235b32e99a74 100644 (file)
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <asm/mach-types.h>
-#include <mach/audmux.h>
 
 #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 (file)
index 0000000..7b16266
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * 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 <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#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 <s.hauer@pengutronix.de>");
+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 (file)
index 0000000..5136d94
--- /dev/null
@@ -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 */
index 155899c08c0c4c15ddcdf5fe3e6874463c6cb578..dbfad0f6251185918b4dd397504d302a6a234859 100644 (file)
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
 #include <asm/mach-types.h>
-#include <mach/audmux.h>
 #include <mach/iomux-mx27.h>
 
 #include "../codecs/tlv320aic32x4.h"
 #include "imx-ssi.h"
+#include "imx-audmux.h"
 
 #define MX27VIS_AMP_GAIN       0
 #define MX27VIS_AMP_MUTE       1
index a59692e740b4558468280708228b6165422e7924..7dab077f9c30a7914f1bc9a8ea04130dbc0f2114 100644 (file)
@@ -18,7 +18,8 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <asm/mach-types.h>
-#include <mach/audmux.h>
+
+#include "imx-audmux.h"
 
 static struct snd_soc_card imx_phycore;
 
index 37480c90e9979265e43171326d4bfab6310d25f5..15056d6a1643a42558a51677f7fcf5ff092851de 100644 (file)
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include <mach/audmux.h>
-
 #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.