aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-mxc/audmux-v2.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-11 11:33:18 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2010-01-12 04:41:10 -0500
commit7b4e08a77f0cbfe31b47faf082caa02f9c252266 (patch)
treef5d2687b06045341b1b81ec6155366d78be98817 /arch/arm/plat-mxc/audmux-v2.c
parent3d661ac187e72af71d3bb7d48a46012180a6fc46 (diff)
MXC: Add AUDMUXv2 register decode to debugfs
Since AUDMUX configuration appears to be one of the common stumbling blocks for people setting up i.MX audio try to provide some diagnostic information describing the current setup to assisist people in working out what's going on. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/plat-mxc/audmux-v2.c')
-rw-r--r--arch/arm/plat-mxc/audmux-v2.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index 6f21096086fd..b06954a84436 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -23,6 +23,7 @@
23#include <linux/err.h> 23#include <linux/err.h>
24#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/debugfs.h>
26#include <mach/audmux.h> 27#include <mach/audmux.h>
27#include <mach/hardware.h> 28#include <mach/hardware.h>
28 29
@@ -32,6 +33,140 @@ static void __iomem *audmux_base;
32#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8) 33#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8)
33#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) 34#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
34 35
36#ifdef CONFIG_DEBUG_FS
37static struct dentry *audmux_debugfs_root;
38
39static int audmux_open_file(struct inode *inode, struct file *file)
40{
41 file->private_data = inode->i_private;
42 return 0;
43}
44
45/* There is an annoying discontinuity in the SSI numbering with regard
46 * to the Linux number of the devices */
47static const char *audmux_port_string(int port)
48{
49 switch (port) {
50 case MX31_AUDMUX_PORT1_SSI0:
51 return "imx-ssi.0";
52 case MX31_AUDMUX_PORT2_SSI1:
53 return "imx-ssi.1";
54 case MX31_AUDMUX_PORT3_SSI_PINS_3:
55 return "SSI3";
56 case MX31_AUDMUX_PORT4_SSI_PINS_4:
57 return "SSI4";
58 case MX31_AUDMUX_PORT5_SSI_PINS_5:
59 return "SSI5";
60 case MX31_AUDMUX_PORT6_SSI_PINS_6:
61 return "SSI6";
62 default:
63 return "UNKNOWN";
64 }
65}
66
67static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
68 size_t count, loff_t *ppos)
69{
70 ssize_t ret;
71 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
72 int port = (int)file->private_data;
73 u32 pdcr, ptcr;
74
75 if (!buf)
76 return -ENOMEM;
77
78 if (audmux_clk)
79 clk_enable(audmux_clk);
80
81 ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port));
82 pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port));
83
84 if (audmux_clk)
85 clk_disable(audmux_clk);
86
87 ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
88 pdcr, ptcr);
89
90 if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR)
91 ret += snprintf(buf + ret, PAGE_SIZE - ret,
92 "TxFS output from %s, ",
93 audmux_port_string((ptcr >> 27) & 0x7));
94 else
95 ret += snprintf(buf + ret, PAGE_SIZE - ret,
96 "TxFS input, ");
97
98 if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR)
99 ret += snprintf(buf + ret, PAGE_SIZE - ret,
100 "TxClk output from %s",
101 audmux_port_string((ptcr >> 22) & 0x7));
102 else
103 ret += snprintf(buf + ret, PAGE_SIZE - ret,
104 "TxClk input");
105
106 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
107
108 if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) {
109 ret += snprintf(buf + ret, PAGE_SIZE - ret,
110 "Port is symmetric");
111 } else {
112 if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR)
113 ret += snprintf(buf + ret, PAGE_SIZE - ret,
114 "RxFS output from %s, ",
115 audmux_port_string((ptcr >> 17) & 0x7));
116 else
117 ret += snprintf(buf + ret, PAGE_SIZE - ret,
118 "RxFS input, ");
119
120 if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR)
121 ret += snprintf(buf + ret, PAGE_SIZE - ret,
122 "RxClk output from %s",
123 audmux_port_string((ptcr >> 12) & 0x7));
124 else
125 ret += snprintf(buf + ret, PAGE_SIZE - ret,
126 "RxClk input");
127 }
128
129 ret += snprintf(buf + ret, PAGE_SIZE - ret,
130 "\nData received from %s\n",
131 audmux_port_string((pdcr >> 13) & 0x7));
132
133 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
134
135 kfree(buf);
136
137 return ret;
138}
139
140static const struct file_operations audmux_debugfs_fops = {
141 .open = audmux_open_file,
142 .read = audmux_read_file,
143};
144
145static void audmux_debugfs_init(void)
146{
147 int i;
148 char buf[20];
149
150 audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
151 if (!audmux_debugfs_root) {
152 pr_warning("Failed to create AUDMUX debugfs root\n");
153 return;
154 }
155
156 for (i = 1; i < 8; i++) {
157 snprintf(buf, sizeof(buf), "ssi%d", i);
158 if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
159 (void *)i, &audmux_debugfs_fops))
160 pr_warning("Failed to create AUDMUX port %d debugfs file\n",
161 i);
162 }
163}
164#else
165static inline void audmux_debugfs_init(void)
166{
167}
168#endif
169
35int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, 170int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
36 unsigned int pdcr) 171 unsigned int pdcr)
37{ 172{
@@ -68,6 +203,8 @@ static int mxc_audmux_v2_init(void)
68 if (cpu_is_mx31() || cpu_is_mx35()) 203 if (cpu_is_mx31() || cpu_is_mx35())
69 audmux_base = IO_ADDRESS(AUDMUX_BASE_ADDR); 204 audmux_base = IO_ADDRESS(AUDMUX_BASE_ADDR);
70 205
206 audmux_debugfs_init();
207
71 return 0; 208 return 0;
72} 209}
73 210