aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/Kconfig8
-rw-r--r--arch/arm/plat-omap/Makefile2
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h333
-rw-r--r--arch/arm/plat-omap/mcbsp.c1361
4 files changed, 0 insertions, 1704 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index aa59f4247dc5..8f81503a4df7 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -110,14 +110,6 @@ config OMAP_MUX_WARNINGS
110 to change the pin multiplexing setup. When there are no warnings 110 to change the pin multiplexing setup. When there are no warnings
111 printed, it's safe to deselect OMAP_MUX for your product. 111 printed, it's safe to deselect OMAP_MUX for your product.
112 112
113config OMAP_MCBSP
114 bool "McBSP support"
115 depends on ARCH_OMAP
116 default y
117 help
118 Say Y here if you want support for the OMAP Multichannel
119 Buffered Serial Port.
120
121config OMAP_MBOX_FWK 113config OMAP_MBOX_FWK
122 tristate "Mailbox framework support" 114 tristate "Mailbox framework support"
123 depends on ARCH_OMAP 115 depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9a584614e7e6..c0fe2757b695 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -17,8 +17,6 @@ obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
17obj-$(CONFIG_ARCH_OMAP3) += omap_device.o 17obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
18obj-$(CONFIG_ARCH_OMAP4) += omap_device.o 18obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
19 19
20obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
21
22obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o 20obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
23obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o 21obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
24obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o 22obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 8fa74e2c9d6e..18814127809a 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -27,271 +27,10 @@
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28#include <linux/clk.h> 28#include <linux/clk.h>
29 29
30/* macro for building platform_device for McBSP ports */
31#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
32static struct platform_device omap_mcbsp##port_nr = { \
33 .name = "omap-mcbsp-dai", \
34 .id = port_nr - 1, \
35}
36
37#define MCBSP_CONFIG_TYPE2 0x2 30#define MCBSP_CONFIG_TYPE2 0x2
38#define MCBSP_CONFIG_TYPE3 0x3 31#define MCBSP_CONFIG_TYPE3 0x3
39#define MCBSP_CONFIG_TYPE4 0x4 32#define MCBSP_CONFIG_TYPE4 0x4
40 33
41/* McBSP register numbers. Register address offset = num * reg_step */
42enum {
43 /* Common registers */
44 OMAP_MCBSP_REG_SPCR2 = 4,
45 OMAP_MCBSP_REG_SPCR1,
46 OMAP_MCBSP_REG_RCR2,
47 OMAP_MCBSP_REG_RCR1,
48 OMAP_MCBSP_REG_XCR2,
49 OMAP_MCBSP_REG_XCR1,
50 OMAP_MCBSP_REG_SRGR2,
51 OMAP_MCBSP_REG_SRGR1,
52 OMAP_MCBSP_REG_MCR2,
53 OMAP_MCBSP_REG_MCR1,
54 OMAP_MCBSP_REG_RCERA,
55 OMAP_MCBSP_REG_RCERB,
56 OMAP_MCBSP_REG_XCERA,
57 OMAP_MCBSP_REG_XCERB,
58 OMAP_MCBSP_REG_PCR0,
59 OMAP_MCBSP_REG_RCERC,
60 OMAP_MCBSP_REG_RCERD,
61 OMAP_MCBSP_REG_XCERC,
62 OMAP_MCBSP_REG_XCERD,
63 OMAP_MCBSP_REG_RCERE,
64 OMAP_MCBSP_REG_RCERF,
65 OMAP_MCBSP_REG_XCERE,
66 OMAP_MCBSP_REG_XCERF,
67 OMAP_MCBSP_REG_RCERG,
68 OMAP_MCBSP_REG_RCERH,
69 OMAP_MCBSP_REG_XCERG,
70 OMAP_MCBSP_REG_XCERH,
71
72 /* OMAP1-OMAP2420 registers */
73 OMAP_MCBSP_REG_DRR2 = 0,
74 OMAP_MCBSP_REG_DRR1,
75 OMAP_MCBSP_REG_DXR2,
76 OMAP_MCBSP_REG_DXR1,
77
78 /* OMAP2430 and onwards */
79 OMAP_MCBSP_REG_DRR = 0,
80 OMAP_MCBSP_REG_DXR = 2,
81 OMAP_MCBSP_REG_SYSCON = 35,
82 OMAP_MCBSP_REG_THRSH2,
83 OMAP_MCBSP_REG_THRSH1,
84 OMAP_MCBSP_REG_IRQST = 40,
85 OMAP_MCBSP_REG_IRQEN,
86 OMAP_MCBSP_REG_WAKEUPEN,
87 OMAP_MCBSP_REG_XCCR,
88 OMAP_MCBSP_REG_RCCR,
89 OMAP_MCBSP_REG_XBUFFSTAT,
90 OMAP_MCBSP_REG_RBUFFSTAT,
91 OMAP_MCBSP_REG_SSELCR,
92};
93
94/* OMAP3 sidetone control registers */
95#define OMAP_ST_REG_REV 0x00
96#define OMAP_ST_REG_SYSCONFIG 0x10
97#define OMAP_ST_REG_IRQSTATUS 0x18
98#define OMAP_ST_REG_IRQENABLE 0x1C
99#define OMAP_ST_REG_SGAINCR 0x24
100#define OMAP_ST_REG_SFIRCR 0x28
101#define OMAP_ST_REG_SSELCR 0x2C
102
103/************************** McBSP SPCR1 bit definitions ***********************/
104#define RRST 0x0001
105#define RRDY 0x0002
106#define RFULL 0x0004
107#define RSYNC_ERR 0x0008
108#define RINTM(value) ((value)<<4) /* bits 4:5 */
109#define ABIS 0x0040
110#define DXENA 0x0080
111#define CLKSTP(value) ((value)<<11) /* bits 11:12 */
112#define RJUST(value) ((value)<<13) /* bits 13:14 */
113#define ALB 0x8000
114#define DLB 0x8000
115
116/************************** McBSP SPCR2 bit definitions ***********************/
117#define XRST 0x0001
118#define XRDY 0x0002
119#define XEMPTY 0x0004
120#define XSYNC_ERR 0x0008
121#define XINTM(value) ((value)<<4) /* bits 4:5 */
122#define GRST 0x0040
123#define FRST 0x0080
124#define SOFT 0x0100
125#define FREE 0x0200
126
127/************************** McBSP PCR bit definitions *************************/
128#define CLKRP 0x0001
129#define CLKXP 0x0002
130#define FSRP 0x0004
131#define FSXP 0x0008
132#define DR_STAT 0x0010
133#define DX_STAT 0x0020
134#define CLKS_STAT 0x0040
135#define SCLKME 0x0080
136#define CLKRM 0x0100
137#define CLKXM 0x0200
138#define FSRM 0x0400
139#define FSXM 0x0800
140#define RIOEN 0x1000
141#define XIOEN 0x2000
142#define IDLE_EN 0x4000
143
144/************************** McBSP RCR1 bit definitions ************************/
145#define RWDLEN1(value) ((value)<<5) /* Bits 5:7 */
146#define RFRLEN1(value) ((value)<<8) /* Bits 8:14 */
147
148/************************** McBSP XCR1 bit definitions ************************/
149#define XWDLEN1(value) ((value)<<5) /* Bits 5:7 */
150#define XFRLEN1(value) ((value)<<8) /* Bits 8:14 */
151
152/*************************** McBSP RCR2 bit definitions ***********************/
153#define RDATDLY(value) (value) /* Bits 0:1 */
154#define RFIG 0x0004
155#define RCOMPAND(value) ((value)<<3) /* Bits 3:4 */
156#define RWDLEN2(value) ((value)<<5) /* Bits 5:7 */
157#define RFRLEN2(value) ((value)<<8) /* Bits 8:14 */
158#define RPHASE 0x8000
159
160/*************************** McBSP XCR2 bit definitions ***********************/
161#define XDATDLY(value) (value) /* Bits 0:1 */
162#define XFIG 0x0004
163#define XCOMPAND(value) ((value)<<3) /* Bits 3:4 */
164#define XWDLEN2(value) ((value)<<5) /* Bits 5:7 */
165#define XFRLEN2(value) ((value)<<8) /* Bits 8:14 */
166#define XPHASE 0x8000
167
168/************************* McBSP SRGR1 bit definitions ************************/
169#define CLKGDV(value) (value) /* Bits 0:7 */
170#define FWID(value) ((value)<<8) /* Bits 8:15 */
171
172/************************* McBSP SRGR2 bit definitions ************************/
173#define FPER(value) (value) /* Bits 0:11 */
174#define FSGM 0x1000
175#define CLKSM 0x2000
176#define CLKSP 0x4000
177#define GSYNC 0x8000
178
179/************************* McBSP MCR1 bit definitions *************************/
180#define RMCM 0x0001
181#define RCBLK(value) ((value)<<2) /* Bits 2:4 */
182#define RPABLK(value) ((value)<<5) /* Bits 5:6 */
183#define RPBBLK(value) ((value)<<7) /* Bits 7:8 */
184
185/************************* McBSP MCR2 bit definitions *************************/
186#define XMCM(value) (value) /* Bits 0:1 */
187#define XCBLK(value) ((value)<<2) /* Bits 2:4 */
188#define XPABLK(value) ((value)<<5) /* Bits 5:6 */
189#define XPBBLK(value) ((value)<<7) /* Bits 7:8 */
190
191/*********************** McBSP XCCR bit definitions *************************/
192#define EXTCLKGATE 0x8000
193#define PPCONNECT 0x4000
194#define DXENDLY(value) ((value)<<12) /* Bits 12:13 */
195#define XFULL_CYCLE 0x0800
196#define DILB 0x0020
197#define XDMAEN 0x0008
198#define XDISABLE 0x0001
199
200/********************** McBSP RCCR bit definitions *************************/
201#define RFULL_CYCLE 0x0800
202#define RDMAEN 0x0008
203#define RDISABLE 0x0001
204
205/********************** McBSP SYSCONFIG bit definitions ********************/
206#define CLOCKACTIVITY(value) ((value)<<8)
207#define SIDLEMODE(value) ((value)<<3)
208#define ENAWAKEUP 0x0004
209#define SOFTRST 0x0002
210
211/********************** McBSP SSELCR bit definitions ***********************/
212#define SIDETONEEN 0x0400
213
214/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
215#define ST_AUTOIDLE 0x0001
216
217/********************** McBSP Sidetone SGAINCR bit definitions *************/
218#define ST_CH1GAIN(value) ((value<<16)) /* Bits 16:31 */
219#define ST_CH0GAIN(value) (value) /* Bits 0:15 */
220
221/********************** McBSP Sidetone SFIRCR bit definitions **************/
222#define ST_FIRCOEFF(value) (value) /* Bits 0:15 */
223
224/********************** McBSP Sidetone SSELCR bit definitions **************/
225#define ST_COEFFWRDONE 0x0004
226#define ST_COEFFWREN 0x0002
227#define ST_SIDETONEEN 0x0001
228
229/********************** McBSP DMA operating modes **************************/
230#define MCBSP_DMA_MODE_ELEMENT 0
231#define MCBSP_DMA_MODE_THRESHOLD 1
232#define MCBSP_DMA_MODE_FRAME 2
233
234/********************** McBSP WAKEUPEN bit definitions *********************/
235#define XEMPTYEOFEN 0x4000
236#define XRDYEN 0x0400
237#define XEOFEN 0x0200
238#define XFSXEN 0x0100
239#define XSYNCERREN 0x0080
240#define RRDYEN 0x0008
241#define REOFEN 0x0004
242#define RFSREN 0x0002
243#define RSYNCERREN 0x0001
244
245/* CLKR signal muxing options */
246#define CLKR_SRC_CLKR 0
247#define CLKR_SRC_CLKX 1
248
249/* FSR signal muxing options */
250#define FSR_SRC_FSR 0
251#define FSR_SRC_FSX 1
252
253/* McBSP functional clock sources */
254#define MCBSP_CLKS_PRCM_SRC 0
255#define MCBSP_CLKS_PAD_SRC 1
256
257/* we don't do multichannel for now */
258struct omap_mcbsp_reg_cfg {
259 u16 spcr2;
260 u16 spcr1;
261 u16 rcr2;
262 u16 rcr1;
263 u16 xcr2;
264 u16 xcr1;
265 u16 srgr2;
266 u16 srgr1;
267 u16 mcr2;
268 u16 mcr1;
269 u16 pcr0;
270 u16 rcerc;
271 u16 rcerd;
272 u16 xcerc;
273 u16 xcerd;
274 u16 rcere;
275 u16 rcerf;
276 u16 xcere;
277 u16 xcerf;
278 u16 rcerg;
279 u16 rcerh;
280 u16 xcerg;
281 u16 xcerh;
282 u16 xccr;
283 u16 rccr;
284};
285
286typedef enum {
287 OMAP_MCBSP_WORD_8 = 0,
288 OMAP_MCBSP_WORD_12,
289 OMAP_MCBSP_WORD_16,
290 OMAP_MCBSP_WORD_20,
291 OMAP_MCBSP_WORD_24,
292 OMAP_MCBSP_WORD_32,
293} omap_mcbsp_word_length;
294
295/* Platform specific configuration */ 34/* Platform specific configuration */
296struct omap_mcbsp_ops { 35struct omap_mcbsp_ops {
297 void (*request)(unsigned int); 36 void (*request)(unsigned int);
@@ -312,43 +51,6 @@ struct omap_mcbsp_platform_data {
312 int (*mux_signal)(struct device *dev, const char *signal, const char *src); 51 int (*mux_signal)(struct device *dev, const char *signal, const char *src);
313}; 52};
314 53
315struct omap_mcbsp_st_data {
316 void __iomem *io_base_st;
317 bool running;
318 bool enabled;
319 s16 taps[128]; /* Sidetone filter coefficients */
320 int nr_taps; /* Number of filter coefficients in use */
321 s16 ch0gain;
322 s16 ch1gain;
323};
324
325struct omap_mcbsp {
326 struct device *dev;
327 unsigned long phys_base;
328 unsigned long phys_dma_base;
329 void __iomem *io_base;
330 u8 id;
331 u8 free;
332
333 int rx_irq;
334 int tx_irq;
335
336 /* DMA stuff */
337 u8 dma_rx_sync;
338 u8 dma_tx_sync;
339
340 /* Protect the field .free, while checking if the mcbsp is in use */
341 spinlock_t lock;
342 struct omap_mcbsp_platform_data *pdata;
343 struct clk *fclk;
344 struct omap_mcbsp_st_data *st_data;
345 int dma_op_mode;
346 u16 max_tx_thres;
347 u16 max_rx_thres;
348 void *reg_cache;
349 int reg_cache_size;
350};
351
352/** 54/**
353 * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod 55 * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
354 * @sidetone: name of the sidetone device 56 * @sidetone: name of the sidetone device
@@ -357,39 +59,4 @@ struct omap_mcbsp_dev_attr {
357 const char *sidetone; 59 const char *sidetone;
358}; 60};
359 61
360extern struct omap_mcbsp **mcbsp_ptr;
361extern int omap_mcbsp_count;
362
363int omap_mcbsp_init(void);
364void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
365void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
366void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
367u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
368u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
369u16 omap_mcbsp_get_fifo_size(unsigned int id);
370u16 omap_mcbsp_get_tx_delay(unsigned int id);
371u16 omap_mcbsp_get_rx_delay(unsigned int id);
372int omap_mcbsp_get_dma_op_mode(unsigned int id);
373int omap_mcbsp_request(unsigned int id);
374void omap_mcbsp_free(unsigned int id);
375void omap_mcbsp_start(unsigned int id, int tx, int rx);
376void omap_mcbsp_stop(unsigned int id, int tx, int rx);
377
378/* McBSP functional clock source changing function */
379extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
380
381/* McBSP signal muxing API */
382void omap2_mcbsp1_mux_clkr_src(u8 mux);
383void omap2_mcbsp1_mux_fsr_src(u8 mux);
384
385int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
386int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
387
388/* Sidetone specific API */
389int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
390int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
391int omap_st_enable(unsigned int id);
392int omap_st_disable(unsigned int id);
393int omap_st_is_enabled(unsigned int id);
394
395#endif 62#endif
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
deleted file mode 100644
index 4b15cd7926d7..000000000000
--- a/arch/arm/plat-omap/mcbsp.c
+++ /dev/null
@@ -1,1361 +0,0 @@
1/*
2 * linux/arch/arm/plat-omap/mcbsp.c
3 *
4 * Copyright (C) 2004 Nokia Corporation
5 * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Multichannel mode not supported.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/platform_device.h>
19#include <linux/interrupt.h>
20#include <linux/err.h>
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/io.h>
24#include <linux/slab.h>
25
26#include <plat/mcbsp.h>
27#include <linux/pm_runtime.h>
28
29struct omap_mcbsp **mcbsp_ptr;
30int omap_mcbsp_count;
31
32#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
33#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
34
35static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
36{
37 void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
38
39 if (mcbsp->pdata->reg_size == 2) {
40 ((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
41 __raw_writew((u16)val, addr);
42 } else {
43 ((u32 *)mcbsp->reg_cache)[reg] = val;
44 __raw_writel(val, addr);
45 }
46}
47
48static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
49{
50 void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
51
52 if (mcbsp->pdata->reg_size == 2) {
53 return !from_cache ? __raw_readw(addr) :
54 ((u16 *)mcbsp->reg_cache)[reg];
55 } else {
56 return !from_cache ? __raw_readl(addr) :
57 ((u32 *)mcbsp->reg_cache)[reg];
58 }
59}
60
61static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
62{
63 __raw_writel(val, mcbsp->st_data->io_base_st + reg);
64}
65
66static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
67{
68 return __raw_readl(mcbsp->st_data->io_base_st + reg);
69}
70
71#define MCBSP_READ(mcbsp, reg) \
72 omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
73#define MCBSP_WRITE(mcbsp, reg, val) \
74 omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val)
75#define MCBSP_READ_CACHE(mcbsp, reg) \
76 omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
77
78#define MCBSP_ST_READ(mcbsp, reg) \
79 omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
80#define MCBSP_ST_WRITE(mcbsp, reg, val) \
81 omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
82
83static void omap_mcbsp_dump_reg(u8 id)
84{
85 struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
86
87 dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
88 dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n",
89 MCBSP_READ(mcbsp, DRR2));
90 dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n",
91 MCBSP_READ(mcbsp, DRR1));
92 dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n",
93 MCBSP_READ(mcbsp, DXR2));
94 dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n",
95 MCBSP_READ(mcbsp, DXR1));
96 dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n",
97 MCBSP_READ(mcbsp, SPCR2));
98 dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n",
99 MCBSP_READ(mcbsp, SPCR1));
100 dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n",
101 MCBSP_READ(mcbsp, RCR2));
102 dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n",
103 MCBSP_READ(mcbsp, RCR1));
104 dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n",
105 MCBSP_READ(mcbsp, XCR2));
106 dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n",
107 MCBSP_READ(mcbsp, XCR1));
108 dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n",
109 MCBSP_READ(mcbsp, SRGR2));
110 dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n",
111 MCBSP_READ(mcbsp, SRGR1));
112 dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n",
113 MCBSP_READ(mcbsp, PCR0));
114 dev_dbg(mcbsp->dev, "***********************\n");
115}
116
117static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
118{
119 struct omap_mcbsp *mcbsp_tx = dev_id;
120 u16 irqst_spcr2;
121
122 irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2);
123 dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
124
125 if (irqst_spcr2 & XSYNC_ERR) {
126 dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
127 irqst_spcr2);
128 /* Writing zero to XSYNC_ERR clears the IRQ */
129 MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
130 }
131
132 return IRQ_HANDLED;
133}
134
135static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
136{
137 struct omap_mcbsp *mcbsp_rx = dev_id;
138 u16 irqst_spcr1;
139
140 irqst_spcr1 = MCBSP_READ(mcbsp_rx, SPCR1);
141 dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1);
142
143 if (irqst_spcr1 & RSYNC_ERR) {
144 dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
145 irqst_spcr1);
146 /* Writing zero to RSYNC_ERR clears the IRQ */
147 MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
148 }
149
150 return IRQ_HANDLED;
151}
152
153/*
154 * omap_mcbsp_config simply write a config to the
155 * appropriate McBSP.
156 * You either call this function or set the McBSP registers
157 * by yourself before calling omap_mcbsp_start().
158 */
159void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
160{
161 struct omap_mcbsp *mcbsp;
162
163 if (!omap_mcbsp_check_valid_id(id)) {
164 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
165 return;
166 }
167 mcbsp = id_to_mcbsp_ptr(id);
168
169 dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n",
170 mcbsp->id, mcbsp->phys_base);
171
172 /* We write the given config */
173 MCBSP_WRITE(mcbsp, SPCR2, config->spcr2);
174 MCBSP_WRITE(mcbsp, SPCR1, config->spcr1);
175 MCBSP_WRITE(mcbsp, RCR2, config->rcr2);
176 MCBSP_WRITE(mcbsp, RCR1, config->rcr1);
177 MCBSP_WRITE(mcbsp, XCR2, config->xcr2);
178 MCBSP_WRITE(mcbsp, XCR1, config->xcr1);
179 MCBSP_WRITE(mcbsp, SRGR2, config->srgr2);
180 MCBSP_WRITE(mcbsp, SRGR1, config->srgr1);
181 MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
182 MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
183 MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
184 if (mcbsp->pdata->has_ccr) {
185 MCBSP_WRITE(mcbsp, XCCR, config->xccr);
186 MCBSP_WRITE(mcbsp, RCCR, config->rccr);
187 }
188}
189EXPORT_SYMBOL(omap_mcbsp_config);
190
191/**
192 * omap_mcbsp_dma_params - returns the dma channel number
193 * @id - mcbsp id
194 * @stream - indicates the direction of data flow (rx or tx)
195 *
196 * Returns the dma channel number for the rx channel or tx channel
197 * based on the value of @stream for the requested mcbsp given by @id
198 */
199int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream)
200{
201 struct omap_mcbsp *mcbsp;
202
203 if (!omap_mcbsp_check_valid_id(id)) {
204 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
205 return -ENODEV;
206 }
207 mcbsp = id_to_mcbsp_ptr(id);
208
209 if (stream)
210 return mcbsp->dma_rx_sync;
211 else
212 return mcbsp->dma_tx_sync;
213}
214EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
215
216/**
217 * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
218 * @id - mcbsp id
219 * @stream - indicates the direction of data flow (rx or tx)
220 *
221 * Returns the address of mcbsp data transmit register or data receive register
222 * to be used by DMA for transferring/receiving data based on the value of
223 * @stream for the requested mcbsp given by @id
224 */
225int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
226{
227 struct omap_mcbsp *mcbsp;
228 int data_reg;
229
230 if (!omap_mcbsp_check_valid_id(id)) {
231 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
232 return -ENODEV;
233 }
234 mcbsp = id_to_mcbsp_ptr(id);
235
236 if (mcbsp->pdata->reg_size == 2) {
237 if (stream)
238 data_reg = OMAP_MCBSP_REG_DRR1;
239 else
240 data_reg = OMAP_MCBSP_REG_DXR1;
241 } else {
242 if (stream)
243 data_reg = OMAP_MCBSP_REG_DRR;
244 else
245 data_reg = OMAP_MCBSP_REG_DXR;
246 }
247
248 return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
249}
250EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
251
252static void omap_st_on(struct omap_mcbsp *mcbsp)
253{
254 unsigned int w;
255
256 if (mcbsp->pdata->enable_st_clock)
257 mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
258
259 /* Enable McBSP Sidetone */
260 w = MCBSP_READ(mcbsp, SSELCR);
261 MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
262
263 /* Enable Sidetone from Sidetone Core */
264 w = MCBSP_ST_READ(mcbsp, SSELCR);
265 MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
266}
267
268static void omap_st_off(struct omap_mcbsp *mcbsp)
269{
270 unsigned int w;
271
272 w = MCBSP_ST_READ(mcbsp, SSELCR);
273 MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
274
275 w = MCBSP_READ(mcbsp, SSELCR);
276 MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
277
278 if (mcbsp->pdata->enable_st_clock)
279 mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
280}
281
282static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
283{
284 u16 val, i;
285
286 val = MCBSP_ST_READ(mcbsp, SSELCR);
287
288 if (val & ST_COEFFWREN)
289 MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
290
291 MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN);
292
293 for (i = 0; i < 128; i++)
294 MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]);
295
296 i = 0;
297
298 val = MCBSP_ST_READ(mcbsp, SSELCR);
299 while (!(val & ST_COEFFWRDONE) && (++i < 1000))
300 val = MCBSP_ST_READ(mcbsp, SSELCR);
301
302 MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
303
304 if (i == 1000)
305 dev_err(mcbsp->dev, "McBSP FIR load error!\n");
306}
307
308static void omap_st_chgain(struct omap_mcbsp *mcbsp)
309{
310 u16 w;
311 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
312
313 w = MCBSP_ST_READ(mcbsp, SSELCR);
314
315 MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \
316 ST_CH1GAIN(st_data->ch1gain));
317}
318
319int omap_st_set_chgain(unsigned int id, int channel, s16 chgain)
320{
321 struct omap_mcbsp *mcbsp;
322 struct omap_mcbsp_st_data *st_data;
323 int ret = 0;
324
325 if (!omap_mcbsp_check_valid_id(id)) {
326 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
327 return -ENODEV;
328 }
329
330 mcbsp = id_to_mcbsp_ptr(id);
331 st_data = mcbsp->st_data;
332
333 if (!st_data)
334 return -ENOENT;
335
336 spin_lock_irq(&mcbsp->lock);
337 if (channel == 0)
338 st_data->ch0gain = chgain;
339 else if (channel == 1)
340 st_data->ch1gain = chgain;
341 else
342 ret = -EINVAL;
343
344 if (st_data->enabled)
345 omap_st_chgain(mcbsp);
346 spin_unlock_irq(&mcbsp->lock);
347
348 return ret;
349}
350EXPORT_SYMBOL(omap_st_set_chgain);
351
352int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain)
353{
354 struct omap_mcbsp *mcbsp;
355 struct omap_mcbsp_st_data *st_data;
356 int ret = 0;
357
358 if (!omap_mcbsp_check_valid_id(id)) {
359 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
360 return -ENODEV;
361 }
362
363 mcbsp = id_to_mcbsp_ptr(id);
364 st_data = mcbsp->st_data;
365
366 if (!st_data)
367 return -ENOENT;
368
369 spin_lock_irq(&mcbsp->lock);
370 if (channel == 0)
371 *chgain = st_data->ch0gain;
372 else if (channel == 1)
373 *chgain = st_data->ch1gain;
374 else
375 ret = -EINVAL;
376 spin_unlock_irq(&mcbsp->lock);
377
378 return ret;
379}
380EXPORT_SYMBOL(omap_st_get_chgain);
381
382static int omap_st_start(struct omap_mcbsp *mcbsp)
383{
384 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
385
386 if (st_data && st_data->enabled && !st_data->running) {
387 omap_st_fir_write(mcbsp, st_data->taps);
388 omap_st_chgain(mcbsp);
389
390 if (!mcbsp->free) {
391 omap_st_on(mcbsp);
392 st_data->running = 1;
393 }
394 }
395
396 return 0;
397}
398
399int omap_st_enable(unsigned int id)
400{
401 struct omap_mcbsp *mcbsp;
402 struct omap_mcbsp_st_data *st_data;
403
404 if (!omap_mcbsp_check_valid_id(id)) {
405 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
406 return -ENODEV;
407 }
408
409 mcbsp = id_to_mcbsp_ptr(id);
410 st_data = mcbsp->st_data;
411
412 if (!st_data)
413 return -ENODEV;
414
415 spin_lock_irq(&mcbsp->lock);
416 st_data->enabled = 1;
417 omap_st_start(mcbsp);
418 spin_unlock_irq(&mcbsp->lock);
419
420 return 0;
421}
422EXPORT_SYMBOL(omap_st_enable);
423
424static int omap_st_stop(struct omap_mcbsp *mcbsp)
425{
426 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
427
428 if (st_data && st_data->running) {
429 if (!mcbsp->free) {
430 omap_st_off(mcbsp);
431 st_data->running = 0;
432 }
433 }
434
435 return 0;
436}
437
438int omap_st_disable(unsigned int id)
439{
440 struct omap_mcbsp *mcbsp;
441 struct omap_mcbsp_st_data *st_data;
442 int ret = 0;
443
444 if (!omap_mcbsp_check_valid_id(id)) {
445 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
446 return -ENODEV;
447 }
448
449 mcbsp = id_to_mcbsp_ptr(id);
450 st_data = mcbsp->st_data;
451
452 if (!st_data)
453 return -ENODEV;
454
455 spin_lock_irq(&mcbsp->lock);
456 omap_st_stop(mcbsp);
457 st_data->enabled = 0;
458 spin_unlock_irq(&mcbsp->lock);
459
460 return ret;
461}
462EXPORT_SYMBOL(omap_st_disable);
463
464int omap_st_is_enabled(unsigned int id)
465{
466 struct omap_mcbsp *mcbsp;
467 struct omap_mcbsp_st_data *st_data;
468
469 if (!omap_mcbsp_check_valid_id(id)) {
470 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
471 return -ENODEV;
472 }
473
474 mcbsp = id_to_mcbsp_ptr(id);
475 st_data = mcbsp->st_data;
476
477 if (!st_data)
478 return -ENODEV;
479
480
481 return st_data->enabled;
482}
483EXPORT_SYMBOL(omap_st_is_enabled);
484
485/*
486 * omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
487 * The threshold parameter is 1 based, and it is converted (threshold - 1)
488 * for the THRSH2 register.
489 */
490void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
491{
492 struct omap_mcbsp *mcbsp;
493
494 if (!omap_mcbsp_check_valid_id(id)) {
495 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
496 return;
497 }
498 mcbsp = id_to_mcbsp_ptr(id);
499 if (mcbsp->pdata->buffer_size == 0)
500 return;
501
502 if (threshold && threshold <= mcbsp->max_tx_thres)
503 MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
504}
505EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
506
507/*
508 * omap_mcbsp_set_rx_threshold configures the receive threshold in words.
509 * The threshold parameter is 1 based, and it is converted (threshold - 1)
510 * for the THRSH1 register.
511 */
512void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
513{
514 struct omap_mcbsp *mcbsp;
515
516 if (!omap_mcbsp_check_valid_id(id)) {
517 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
518 return;
519 }
520 mcbsp = id_to_mcbsp_ptr(id);
521 if (mcbsp->pdata->buffer_size == 0)
522 return;
523
524 if (threshold && threshold <= mcbsp->max_rx_thres)
525 MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
526}
527EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
528
529/*
530 * omap_mcbsp_get_max_tx_thres just return the current configured
531 * maximum threshold for transmission
532 */
533u16 omap_mcbsp_get_max_tx_threshold(unsigned int id)
534{
535 struct omap_mcbsp *mcbsp;
536
537 if (!omap_mcbsp_check_valid_id(id)) {
538 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
539 return -ENODEV;
540 }
541 mcbsp = id_to_mcbsp_ptr(id);
542
543 return mcbsp->max_tx_thres;
544}
545EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold);
546
547/*
548 * omap_mcbsp_get_max_rx_thres just return the current configured
549 * maximum threshold for reception
550 */
551u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
552{
553 struct omap_mcbsp *mcbsp;
554
555 if (!omap_mcbsp_check_valid_id(id)) {
556 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
557 return -ENODEV;
558 }
559 mcbsp = id_to_mcbsp_ptr(id);
560
561 return mcbsp->max_rx_thres;
562}
563EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
564
565u16 omap_mcbsp_get_fifo_size(unsigned int id)
566{
567 struct omap_mcbsp *mcbsp;
568
569 if (!omap_mcbsp_check_valid_id(id)) {
570 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
571 return -ENODEV;
572 }
573 mcbsp = id_to_mcbsp_ptr(id);
574
575 return mcbsp->pdata->buffer_size;
576}
577EXPORT_SYMBOL(omap_mcbsp_get_fifo_size);
578
579/*
580 * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
581 */
582u16 omap_mcbsp_get_tx_delay(unsigned int id)
583{
584 struct omap_mcbsp *mcbsp;
585 u16 buffstat;
586
587 if (!omap_mcbsp_check_valid_id(id)) {
588 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
589 return -ENODEV;
590 }
591 mcbsp = id_to_mcbsp_ptr(id);
592 if (mcbsp->pdata->buffer_size == 0)
593 return 0;
594
595 /* Returns the number of free locations in the buffer */
596 buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
597
598 /* Number of slots are different in McBSP ports */
599 return mcbsp->pdata->buffer_size - buffstat;
600}
601EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
602
603/*
604 * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
605 * to reach the threshold value (when the DMA will be triggered to read it)
606 */
607u16 omap_mcbsp_get_rx_delay(unsigned int id)
608{
609 struct omap_mcbsp *mcbsp;
610 u16 buffstat, threshold;
611
612 if (!omap_mcbsp_check_valid_id(id)) {
613 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
614 return -ENODEV;
615 }
616 mcbsp = id_to_mcbsp_ptr(id);
617 if (mcbsp->pdata->buffer_size == 0)
618 return 0;
619
620 /* Returns the number of used locations in the buffer */
621 buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
622 /* RX threshold */
623 threshold = MCBSP_READ(mcbsp, THRSH1);
624
625 /* Return the number of location till we reach the threshold limit */
626 if (threshold <= buffstat)
627 return 0;
628 else
629 return threshold - buffstat;
630}
631EXPORT_SYMBOL(omap_mcbsp_get_rx_delay);
632
633/*
634 * omap_mcbsp_get_dma_op_mode just return the current configured
635 * operating mode for the mcbsp channel
636 */
637int omap_mcbsp_get_dma_op_mode(unsigned int id)
638{
639 struct omap_mcbsp *mcbsp;
640 int dma_op_mode;
641
642 if (!omap_mcbsp_check_valid_id(id)) {
643 printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1);
644 return -ENODEV;
645 }
646 mcbsp = id_to_mcbsp_ptr(id);
647
648 dma_op_mode = mcbsp->dma_op_mode;
649
650 return dma_op_mode;
651}
652EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
653
654int omap_mcbsp_request(unsigned int id)
655{
656 struct omap_mcbsp *mcbsp;
657 void *reg_cache;
658 int err;
659
660 if (!omap_mcbsp_check_valid_id(id)) {
661 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
662 return -ENODEV;
663 }
664 mcbsp = id_to_mcbsp_ptr(id);
665
666 reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
667 if (!reg_cache) {
668 return -ENOMEM;
669 }
670
671 spin_lock(&mcbsp->lock);
672 if (!mcbsp->free) {
673 dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
674 mcbsp->id);
675 err = -EBUSY;
676 goto err_kfree;
677 }
678
679 mcbsp->free = false;
680 mcbsp->reg_cache = reg_cache;
681 spin_unlock(&mcbsp->lock);
682
683 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
684 mcbsp->pdata->ops->request(id);
685
686 pm_runtime_get_sync(mcbsp->dev);
687
688 /* Enable wakeup behavior */
689 if (mcbsp->pdata->has_wakeup)
690 MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
691
692 /*
693 * Make sure that transmitter, receiver and sample-rate generator are
694 * not running before activating IRQs.
695 */
696 MCBSP_WRITE(mcbsp, SPCR1, 0);
697 MCBSP_WRITE(mcbsp, SPCR2, 0);
698
699 err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
700 0, "McBSP", (void *)mcbsp);
701 if (err != 0) {
702 dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
703 "for McBSP%d\n", mcbsp->tx_irq,
704 mcbsp->id);
705 goto err_clk_disable;
706 }
707
708 if (mcbsp->rx_irq) {
709 err = request_irq(mcbsp->rx_irq,
710 omap_mcbsp_rx_irq_handler,
711 0, "McBSP", (void *)mcbsp);
712 if (err != 0) {
713 dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
714 "for McBSP%d\n", mcbsp->rx_irq,
715 mcbsp->id);
716 goto err_free_irq;
717 }
718 }
719
720 return 0;
721err_free_irq:
722 free_irq(mcbsp->tx_irq, (void *)mcbsp);
723err_clk_disable:
724 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
725 mcbsp->pdata->ops->free(id);
726
727 /* Disable wakeup behavior */
728 if (mcbsp->pdata->has_wakeup)
729 MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
730
731 pm_runtime_put_sync(mcbsp->dev);
732
733 spin_lock(&mcbsp->lock);
734 mcbsp->free = true;
735 mcbsp->reg_cache = NULL;
736err_kfree:
737 spin_unlock(&mcbsp->lock);
738 kfree(reg_cache);
739
740 return err;
741}
742EXPORT_SYMBOL(omap_mcbsp_request);
743
744void omap_mcbsp_free(unsigned int id)
745{
746 struct omap_mcbsp *mcbsp;
747 void *reg_cache;
748
749 if (!omap_mcbsp_check_valid_id(id)) {
750 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
751 return;
752 }
753 mcbsp = id_to_mcbsp_ptr(id);
754
755 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
756 mcbsp->pdata->ops->free(id);
757
758 /* Disable wakeup behavior */
759 if (mcbsp->pdata->has_wakeup)
760 MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
761
762 pm_runtime_put_sync(mcbsp->dev);
763
764 if (mcbsp->rx_irq)
765 free_irq(mcbsp->rx_irq, (void *)mcbsp);
766 free_irq(mcbsp->tx_irq, (void *)mcbsp);
767
768 reg_cache = mcbsp->reg_cache;
769
770 spin_lock(&mcbsp->lock);
771 if (mcbsp->free)
772 dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
773 else
774 mcbsp->free = true;
775 mcbsp->reg_cache = NULL;
776 spin_unlock(&mcbsp->lock);
777
778 if (reg_cache)
779 kfree(reg_cache);
780}
781EXPORT_SYMBOL(omap_mcbsp_free);
782
783/*
784 * Here we start the McBSP, by enabling transmitter, receiver or both.
785 * If no transmitter or receiver is active prior calling, then sample-rate
786 * generator and frame sync are started.
787 */
788void omap_mcbsp_start(unsigned int id, int tx, int rx)
789{
790 struct omap_mcbsp *mcbsp;
791 int enable_srg = 0;
792 u16 w;
793
794 if (!omap_mcbsp_check_valid_id(id)) {
795 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
796 return;
797 }
798 mcbsp = id_to_mcbsp_ptr(id);
799
800 if (mcbsp->st_data)
801 omap_st_start(mcbsp);
802
803 /* Only enable SRG, if McBSP is master */
804 w = MCBSP_READ_CACHE(mcbsp, PCR0);
805 if (w & (FSXM | FSRM | CLKXM | CLKRM))
806 enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
807 MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
808
809 if (enable_srg) {
810 /* Start the sample generator */
811 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
812 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
813 }
814
815 /* Enable transmitter and receiver */
816 tx &= 1;
817 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
818 MCBSP_WRITE(mcbsp, SPCR2, w | tx);
819
820 rx &= 1;
821 w = MCBSP_READ_CACHE(mcbsp, SPCR1);
822 MCBSP_WRITE(mcbsp, SPCR1, w | rx);
823
824 /*
825 * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
826 * REVISIT: 100us may give enough time for two CLKSRG, however
827 * due to some unknown PM related, clock gating etc. reason it
828 * is now at 500us.
829 */
830 udelay(500);
831
832 if (enable_srg) {
833 /* Start frame sync */
834 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
835 MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
836 }
837
838 if (mcbsp->pdata->has_ccr) {
839 /* Release the transmitter and receiver */
840 w = MCBSP_READ_CACHE(mcbsp, XCCR);
841 w &= ~(tx ? XDISABLE : 0);
842 MCBSP_WRITE(mcbsp, XCCR, w);
843 w = MCBSP_READ_CACHE(mcbsp, RCCR);
844 w &= ~(rx ? RDISABLE : 0);
845 MCBSP_WRITE(mcbsp, RCCR, w);
846 }
847
848 /* Dump McBSP Regs */
849 omap_mcbsp_dump_reg(id);
850}
851EXPORT_SYMBOL(omap_mcbsp_start);
852
853void omap_mcbsp_stop(unsigned int id, int tx, int rx)
854{
855 struct omap_mcbsp *mcbsp;
856 int idle;
857 u16 w;
858
859 if (!omap_mcbsp_check_valid_id(id)) {
860 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
861 return;
862 }
863
864 mcbsp = id_to_mcbsp_ptr(id);
865
866 /* Reset transmitter */
867 tx &= 1;
868 if (mcbsp->pdata->has_ccr) {
869 w = MCBSP_READ_CACHE(mcbsp, XCCR);
870 w |= (tx ? XDISABLE : 0);
871 MCBSP_WRITE(mcbsp, XCCR, w);
872 }
873 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
874 MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
875
876 /* Reset receiver */
877 rx &= 1;
878 if (mcbsp->pdata->has_ccr) {
879 w = MCBSP_READ_CACHE(mcbsp, RCCR);
880 w |= (rx ? RDISABLE : 0);
881 MCBSP_WRITE(mcbsp, RCCR, w);
882 }
883 w = MCBSP_READ_CACHE(mcbsp, SPCR1);
884 MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
885
886 idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
887 MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
888
889 if (idle) {
890 /* Reset the sample rate generator */
891 w = MCBSP_READ_CACHE(mcbsp, SPCR2);
892 MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
893 }
894
895 if (mcbsp->st_data)
896 omap_st_stop(mcbsp);
897}
898EXPORT_SYMBOL(omap_mcbsp_stop);
899
900int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
901{
902 struct omap_mcbsp *mcbsp;
903 const char *src;
904
905 if (!omap_mcbsp_check_valid_id(id)) {
906 pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
907 return -EINVAL;
908 }
909 mcbsp = id_to_mcbsp_ptr(id);
910
911 if (fck_src_id == MCBSP_CLKS_PAD_SRC)
912 src = "clks_ext";
913 else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
914 src = "clks_fclk";
915 else
916 return -EINVAL;
917
918 if (mcbsp->pdata->set_clk_src)
919 return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
920 else
921 return -EINVAL;
922}
923EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
924
925void omap2_mcbsp1_mux_clkr_src(u8 mux)
926{
927 struct omap_mcbsp *mcbsp;
928 const char *src;
929
930 if (mux == CLKR_SRC_CLKR)
931 src = "clkr";
932 else if (mux == CLKR_SRC_CLKX)
933 src = "clkx";
934 else
935 return;
936
937 mcbsp = id_to_mcbsp_ptr(0);
938 if (mcbsp->pdata->mux_signal)
939 mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
940}
941EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
942
943void omap2_mcbsp1_mux_fsr_src(u8 mux)
944{
945 struct omap_mcbsp *mcbsp;
946 const char *src;
947
948 if (mux == FSR_SRC_FSR)
949 src = "fsr";
950 else if (mux == FSR_SRC_FSX)
951 src = "fsx";
952 else
953 return;
954
955 mcbsp = id_to_mcbsp_ptr(0);
956 if (mcbsp->pdata->mux_signal)
957 mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
958}
959EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
960
961#define max_thres(m) (mcbsp->pdata->buffer_size)
962#define valid_threshold(m, val) ((val) <= max_thres(m))
963#define THRESHOLD_PROP_BUILDER(prop) \
964static ssize_t prop##_show(struct device *dev, \
965 struct device_attribute *attr, char *buf) \
966{ \
967 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
968 \
969 return sprintf(buf, "%u\n", mcbsp->prop); \
970} \
971 \
972static ssize_t prop##_store(struct device *dev, \
973 struct device_attribute *attr, \
974 const char *buf, size_t size) \
975{ \
976 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
977 unsigned long val; \
978 int status; \
979 \
980 status = strict_strtoul(buf, 0, &val); \
981 if (status) \
982 return status; \
983 \
984 if (!valid_threshold(mcbsp, val)) \
985 return -EDOM; \
986 \
987 mcbsp->prop = val; \
988 return size; \
989} \
990 \
991static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
992
993THRESHOLD_PROP_BUILDER(max_tx_thres);
994THRESHOLD_PROP_BUILDER(max_rx_thres);
995
996static const char *dma_op_modes[] = {
997 "element", "threshold", "frame",
998};
999
1000static ssize_t dma_op_mode_show(struct device *dev,
1001 struct device_attribute *attr, char *buf)
1002{
1003 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
1004 int dma_op_mode, i = 0;
1005 ssize_t len = 0;
1006 const char * const *s;
1007
1008 dma_op_mode = mcbsp->dma_op_mode;
1009
1010 for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
1011 if (dma_op_mode == i)
1012 len += sprintf(buf + len, "[%s] ", *s);
1013 else
1014 len += sprintf(buf + len, "%s ", *s);
1015 }
1016 len += sprintf(buf + len, "\n");
1017
1018 return len;
1019}
1020
1021static ssize_t dma_op_mode_store(struct device *dev,
1022 struct device_attribute *attr,
1023 const char *buf, size_t size)
1024{
1025 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
1026 const char * const *s;
1027 int i = 0;
1028
1029 for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++)
1030 if (sysfs_streq(buf, *s))
1031 break;
1032
1033 if (i == ARRAY_SIZE(dma_op_modes))
1034 return -EINVAL;
1035
1036 spin_lock_irq(&mcbsp->lock);
1037 if (!mcbsp->free) {
1038 size = -EBUSY;
1039 goto unlock;
1040 }
1041 mcbsp->dma_op_mode = i;
1042
1043unlock:
1044 spin_unlock_irq(&mcbsp->lock);
1045
1046 return size;
1047}
1048
1049static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
1050
1051static const struct attribute *additional_attrs[] = {
1052 &dev_attr_max_tx_thres.attr,
1053 &dev_attr_max_rx_thres.attr,
1054 &dev_attr_dma_op_mode.attr,
1055 NULL,
1056};
1057
1058static const struct attribute_group additional_attr_group = {
1059 .attrs = (struct attribute **)additional_attrs,
1060};
1061
1062static ssize_t st_taps_show(struct device *dev,
1063 struct device_attribute *attr, char *buf)
1064{
1065 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
1066 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
1067 ssize_t status = 0;
1068 int i;
1069
1070 spin_lock_irq(&mcbsp->lock);
1071 for (i = 0; i < st_data->nr_taps; i++)
1072 status += sprintf(&buf[status], (i ? ", %d" : "%d"),
1073 st_data->taps[i]);
1074 if (i)
1075 status += sprintf(&buf[status], "\n");
1076 spin_unlock_irq(&mcbsp->lock);
1077
1078 return status;
1079}
1080
1081static ssize_t st_taps_store(struct device *dev,
1082 struct device_attribute *attr,
1083 const char *buf, size_t size)
1084{
1085 struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
1086 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
1087 int val, tmp, status, i = 0;
1088
1089 spin_lock_irq(&mcbsp->lock);
1090 memset(st_data->taps, 0, sizeof(st_data->taps));
1091 st_data->nr_taps = 0;
1092
1093 do {
1094 status = sscanf(buf, "%d%n", &val, &tmp);
1095 if (status < 0 || status == 0) {
1096 size = -EINVAL;
1097 goto out;
1098 }
1099 if (val < -32768 || val > 32767) {
1100 size = -EINVAL;
1101 goto out;
1102 }
1103 st_data->taps[i++] = val;
1104 buf += tmp;
1105 if (*buf != ',')
1106 break;
1107 buf++;
1108 } while (1);
1109
1110 st_data->nr_taps = i;
1111
1112out:
1113 spin_unlock_irq(&mcbsp->lock);
1114
1115 return size;
1116}
1117
1118static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
1119
1120static const struct attribute *sidetone_attrs[] = {
1121 &dev_attr_st_taps.attr,
1122 NULL,
1123};
1124
1125static const struct attribute_group sidetone_attr_group = {
1126 .attrs = (struct attribute **)sidetone_attrs,
1127};
1128
1129static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
1130 struct resource *res)
1131{
1132 struct omap_mcbsp_st_data *st_data;
1133 int err;
1134
1135 st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL);
1136 if (!st_data) {
1137 err = -ENOMEM;
1138 goto err1;
1139 }
1140
1141 st_data->io_base_st = ioremap(res->start, resource_size(res));
1142 if (!st_data->io_base_st) {
1143 err = -ENOMEM;
1144 goto err2;
1145 }
1146
1147 err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
1148 if (err)
1149 goto err3;
1150
1151 mcbsp->st_data = st_data;
1152 return 0;
1153
1154err3:
1155 iounmap(st_data->io_base_st);
1156err2:
1157 kfree(st_data);
1158err1:
1159 return err;
1160
1161}
1162
1163static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
1164{
1165 struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
1166
1167 sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
1168 iounmap(st_data->io_base_st);
1169 kfree(st_data);
1170}
1171
1172/*
1173 * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
1174 * 730 has only 2 McBSP, and both of them are MPU peripherals.
1175 */
1176static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
1177{
1178 struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
1179 struct omap_mcbsp *mcbsp;
1180 int id = pdev->id - 1;
1181 struct resource *res;
1182 int ret = 0;
1183
1184 if (!pdata) {
1185 dev_err(&pdev->dev, "McBSP device initialized without"
1186 "platform data\n");
1187 ret = -EINVAL;
1188 goto exit;
1189 }
1190
1191 dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id);
1192
1193 if (id >= omap_mcbsp_count) {
1194 dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id);
1195 ret = -EINVAL;
1196 goto exit;
1197 }
1198
1199 mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL);
1200 if (!mcbsp) {
1201 ret = -ENOMEM;
1202 goto exit;
1203 }
1204
1205 spin_lock_init(&mcbsp->lock);
1206 mcbsp->id = id + 1;
1207 mcbsp->free = true;
1208
1209 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
1210 if (!res) {
1211 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1212 if (!res) {
1213 dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory"
1214 "resource\n", __func__, pdev->id);
1215 ret = -ENOMEM;
1216 goto exit;
1217 }
1218 }
1219 mcbsp->phys_base = res->start;
1220 mcbsp->reg_cache_size = resource_size(res);
1221 mcbsp->io_base = ioremap(res->start, resource_size(res));
1222 if (!mcbsp->io_base) {
1223 ret = -ENOMEM;
1224 goto err_ioremap;
1225 }
1226
1227 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
1228 if (!res)
1229 mcbsp->phys_dma_base = mcbsp->phys_base;
1230 else
1231 mcbsp->phys_dma_base = res->start;
1232
1233 mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
1234 mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
1235
1236 /* From OMAP4 there will be a single irq line */
1237 if (mcbsp->tx_irq == -ENXIO)
1238 mcbsp->tx_irq = platform_get_irq(pdev, 0);
1239
1240 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
1241 if (!res) {
1242 dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n",
1243 __func__, pdev->id);
1244 ret = -ENODEV;
1245 goto err_res;
1246 }
1247 mcbsp->dma_rx_sync = res->start;
1248
1249 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
1250 if (!res) {
1251 dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n",
1252 __func__, pdev->id);
1253 ret = -ENODEV;
1254 goto err_res;
1255 }
1256 mcbsp->dma_tx_sync = res->start;
1257
1258 mcbsp->fclk = clk_get(&pdev->dev, "fck");
1259 if (IS_ERR(mcbsp->fclk)) {
1260 ret = PTR_ERR(mcbsp->fclk);
1261 dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
1262 goto err_res;
1263 }
1264
1265 mcbsp->pdata = pdata;
1266 mcbsp->dev = &pdev->dev;
1267 mcbsp_ptr[id] = mcbsp;
1268 platform_set_drvdata(pdev, mcbsp);
1269 pm_runtime_enable(mcbsp->dev);
1270
1271 mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
1272 if (mcbsp->pdata->buffer_size) {
1273 /*
1274 * Initially configure the maximum thresholds to a safe value.
1275 * The McBSP FIFO usage with these values should not go under
1276 * 16 locations.
1277 * If the whole FIFO without safety buffer is used, than there
1278 * is a possibility that the DMA will be not able to push the
1279 * new data on time, causing channel shifts in runtime.
1280 */
1281 mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
1282 mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
1283
1284 ret = sysfs_create_group(&mcbsp->dev->kobj,
1285 &additional_attr_group);
1286 if (ret) {
1287 dev_err(mcbsp->dev,
1288 "Unable to create additional controls\n");
1289 goto err_thres;
1290 }
1291 } else {
1292 mcbsp->max_tx_thres = -EINVAL;
1293 mcbsp->max_rx_thres = -EINVAL;
1294 }
1295
1296 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
1297 if (res) {
1298 ret = omap_st_add(mcbsp, res);
1299 if (ret) {
1300 dev_err(mcbsp->dev,
1301 "Unable to create sidetone controls\n");
1302 goto err_st;
1303 }
1304 }
1305
1306 return 0;
1307
1308err_st:
1309 if (mcbsp->pdata->buffer_size)
1310 sysfs_remove_group(&mcbsp->dev->kobj,
1311 &additional_attr_group);
1312err_thres:
1313 clk_put(mcbsp->fclk);
1314err_res:
1315 iounmap(mcbsp->io_base);
1316err_ioremap:
1317 kfree(mcbsp);
1318exit:
1319 return ret;
1320}
1321
1322static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
1323{
1324 struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
1325
1326 platform_set_drvdata(pdev, NULL);
1327 if (mcbsp) {
1328
1329 if (mcbsp->pdata && mcbsp->pdata->ops &&
1330 mcbsp->pdata->ops->free)
1331 mcbsp->pdata->ops->free(mcbsp->id);
1332
1333 if (mcbsp->pdata->buffer_size)
1334 sysfs_remove_group(&mcbsp->dev->kobj,
1335 &additional_attr_group);
1336
1337 if (mcbsp->st_data)
1338 omap_st_remove(mcbsp);
1339
1340 clk_put(mcbsp->fclk);
1341
1342 iounmap(mcbsp->io_base);
1343 kfree(mcbsp);
1344 }
1345
1346 return 0;
1347}
1348
1349static struct platform_driver omap_mcbsp_driver = {
1350 .probe = omap_mcbsp_probe,
1351 .remove = __devexit_p(omap_mcbsp_remove),
1352 .driver = {
1353 .name = "omap-mcbsp",
1354 },
1355};
1356
1357int __init omap_mcbsp_init(void)
1358{
1359 /* Register the McBSP driver */
1360 return platform_driver_register(&omap_mcbsp_driver);
1361}