summaryrefslogtreecommitdiff
path: root/include/linux/tdm.h
blob: 93ec1c0c41ae81c9420f3c68ed888300e354c4cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
/* include/linux/tdm.h
 *
 * Copyright 2012 Freescale Semiconductor, Inc.
 *
 * tdm.h - definitions for the tdm-device framework interface
 *
 * Author:Hemant Agrawal <hemant@freescale.com>
 *	Rajesh Gumasta <rajesh.gumasta@freescale.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the  GNU General Public License along
 * with this program; if not, write  to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#ifndef _LINUX_TDM_H
#define _LINUX_TDM_H

#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>	/* for struct device */
#include <linux/sched.h>	/* for completion */
#include <linux/mutex.h>
#include <linux/interrupt.h>

#define CHANNEL_8BIT_LIN	0	/* 8 bit linear */
#define CHANNEL_8BIT_ULAW	1	/* 8 bit Mu-law */
#define CHANNEL_8BIT_ALAW	2	/* 8 bit A-law */
#define CHANNEL_16BIT_LIN	3	/* 16 bit Linear */

#define NUM_CHANNELS		16
#define NUM_SAMPLES_PER_MS	8		/* 8 samples per milli sec per
						 channel. Req for voice data */
#define NUM_MS			10
#define NUM_SAMPLES_PER_FRAME	(NUM_MS * NUM_SAMPLES_PER_MS) /* Number of
						samples for 1 client buffer */
#define NUM_OF_TDM_BUF		3

/* General options */

struct tdm_adapt_algorithm;
struct tdm_adapter;
struct tdm_port;
struct tdm_driver;

/* Align addr on a size boundary - adjust address up if needed */
/* returns min value greater than size which is multiple of alignment */
static inline int ALIGN_SIZE(u64 size, u32 alignment)
{
	return (size + alignment - 1) & (~(alignment - 1));
}

int tdm_master_send(struct tdm_adapter *adap, void **buf, int count);
int tdm_master_recv(struct tdm_adapter *adap, void **buf);
int tdm_read_direct(struct tdm_adapter *adap, u8 *buf, u32 len);
int tdm_write_direct(struct tdm_adapter *adap, u8 *buf, u32 len);

/**
 * struct tdm_driver - represent an TDM device driver
 * @class: What kind of tdm device we instantiate (for detect)
 * @id:Driver id
 * @name: Name of the driver
 * @attach_adapter: Callback for device addition (for legacy drivers)
 * @detach_adapter: Callback for device removal (for legacy drivers)
 * @probe: Callback for device binding
 * @remove: Callback for device unbinding
 * @shutdown: Callback for device shutdown
 * @suspend: Callback for device suspend
 * @resume: Callback for device resume
 * @command: Callback for sending commands to device
 * @id_table: List of TDM devices supported by this driver
 * @list: List of drivers created (for tdm-core use only)
 */
struct tdm_driver {
	unsigned int class;
	unsigned int id;
	char name[TDM_NAME_SIZE];

	int (*attach_adapter)(struct tdm_adapter *);
	int (*detach_adapter)(struct tdm_adapter *);

	/* Standard driver model interfaces */
	int (*probe)(const struct tdm_device_id *);
	int (*remove)(void);

	/* driver model interfaces that don't relate to enumeration */
	void (*shutdown)(void);
	int (*suspend)(pm_message_t mesg);
	int (*resume)(void);

	/* a ioctl like command that can be used to perform specific functions
	 * with the device.
	 */
	int (*command)(unsigned int cmd, void *arg);

	const struct tdm_device_id *id_table;

	/* The associated adapter for this driver */
	struct tdm_adapter *adapter;
	struct list_head list;
};

/* tdm per port statistics structure, used for providing and storing tdm port
 * statistics.
 */
struct tdm_port_stats {
	unsigned int rx_pkt_count;	/* Rx frame count per channel */
	unsigned int rx_pkt_drop_count;	/* Rx drop count per channel to
					 clean space for new buffer */
	unsigned int tx_pkt_count;	/* Tx frame count per channel */
	unsigned int tx_pkt_conf_count;	/* Tx frame confirmation count per
					 channel */
	unsigned int tx_pkt_drop_count;	/* Tx drop count per channel due to
					 queue full */
};


/* tdm Buffer Descriptor, used for Creating Interleaved and De-interleaved
 * FIFOs
 */
struct tdm_bd {
	unsigned char flag;		/* BD is full or empty */
	unsigned char wrap;		/* BD is last in the queue */
	unsigned short length;	/* Length of Data in BD */
	/*TODO: use dyanmic memory */
	unsigned short p_data[NUM_SAMPLES_PER_FRAME];	/* Data Pointer */
	unsigned long offset;	/* Offset of the Data Pointer to be used */
};

#define TDM_CH_RX_BD_RING_SIZE	3
#define TDM_CH_TX_BD_RING_SIZE	3

/* tdm RX-TX Channelised Data */
struct tdm_port_data {
	struct tdm_bd rx_data_fifo[TDM_CH_RX_BD_RING_SIZE]; /* Rx Channel Data
								BD Ring */
	struct tdm_bd *rx_in_data;	/* Current Channel Rx BD to be filled by
						de-interleave function */
	struct tdm_bd *rx_out_data;	/* Current Channel Rx BD to be
							read by App */
	struct tdm_bd tx_data_fifo[TDM_CH_TX_BD_RING_SIZE]; /* Tx Channel Data
								BD Ring */
	struct tdm_bd *tx_in_data;	/* Current Channel Tx BD to be
						 filled by App */
	struct tdm_bd *tx_out_data;	/* Current Channel Tx BD to be read by
						interleave function */
	spinlock_t rx_channel_lock;	/* Spin Lock for Rx Channel */
	spinlock_t tx_channel_lock;	/* Spin Lock for Tx Channel */
};

/* structure tdm_port_cfg - contains configuration params for a port */
struct tdm_port_cfg {
	unsigned short port_mode;
};

/* struct tdm_port - represent an TDM ports for a device */
struct tdm_port {
	unsigned short port_id;
	unsigned short in_use;		/* Port is enabled? */
	uint16_t rx_max_frames;		/* Received Port frames
					 before allowing Read Operation in
					 Port Mode */

	struct tdm_port_stats port_stat;/* A structure parameters defining
					 TDM port statistics. */
	struct tdm_port_data *p_port_data;	/* a structure parameters
						defining tdm channelised data */

	struct tdm_driver *driver;	/* driver for this port */
	struct tdm_adapter *adapter;	/* adapter for this port */
	struct list_head list;		/* list of ports */
	struct list_head mychannels;	/* list of channels, created on this
					 port*/
	spinlock_t ch_list_lock;	/* Spin Lock for channel_list */
	struct tdm_port_cfg port_cfg;/* A structure parameters defining
					 TDM port configuration. */
};

/* tdm RX-TX Channelised Data */
struct tdm_ch_data {
	struct tdm_bd rx_data_fifo[TDM_CH_RX_BD_RING_SIZE]; /* Rx Port Data BD
								Ring */
	struct tdm_bd *rx_in_data;	/* Current Port Rx BD to be filled by
						de-interleave function */
	struct tdm_bd *rx_out_data; /* Current Port Rx BD to be read by App */
	struct tdm_bd tx_data_fifo[TDM_CH_TX_BD_RING_SIZE]; /* Tx Port Data BD
								Ring */
	struct tdm_bd *tx_in_data;	/* Current Port Tx BD to be filled by
						App */
	struct tdm_bd *tx_out_data;	/* Current Port Tx BD to be read by
						interleave function */
	spinlock_t rx_channel_lock;	/* Spin Lock for Rx Port */
	spinlock_t tx_channel_lock;	/* Spin Lock for Tx Port */
};

/* Channel config params */
struct tdm_ch_cfg {
	unsigned short num_slots;
	unsigned short first_slot;
};

/* struct tdm_channel- represent a TDM channel for a port */
struct tdm_channel {
	u16 ch_id;			/* logical channel number */
	struct list_head list;		/* list of channels in a port*/
	struct tdm_port *port;		/* port for this channel */
	u16 in_use;			/* channel is enabled? */
	struct tdm_ch_cfg ch_cfg;	/* channel configuration */
	struct tdm_ch_data *p_ch_data;	/* data storage space for channel */
	wait_queue_head_t ch_wait_queue;/* waitQueue for RX Channel Data */
};

/* tdm_adapt_algorithm is for accessing the routines of device */
struct tdm_adapt_algorithm {
	u32 (*tdm_read)(struct tdm_adapter *, u16 **);
	u32 (*tdm_get_write_buf)(struct tdm_adapter *, u16 **);
	int (*tdm_read_simple)(struct tdm_adapter *, u8 *, u32 len);
	int (*tdm_write_simple)(struct tdm_adapter *, u8 *, u32 len);
	u32 (*tdm_write)(struct tdm_adapter *, void * , unsigned int len);
	int (*tdm_enable)(struct tdm_adapter *);
	int (*tdm_disable)(struct tdm_adapter *);
};

/* tdm_adapter_mode is to define in mode of the device */
enum tdm_adapter_mode {
	e_TDM_ADAPTER_MODE_NONE = 0x00,
	e_TDM_ADAPTER_MODE_T1 = 0x01,
	e_TDM_ADAPTER_MODE_E1 = 0x02,
	e_TDM_ADAPTER_MODE_T1_RAW = 0x10,
	e_TDM_ADAPTER_MODE_E1_RAW = 0x20,
};

/* tdm_port_mode defines the mode in which the port is configured to operate
 * It can be channelized/full/fractional.
 */
enum tdm_port_mode {
	e_TDM_PORT_CHANNELIZED = 0	/* Channelized mode */
	, e_TDM_PORT_FULL = 1		/* Full mode */
	, e_TDM_PORT_FRACTIONAL = 2	/* Fractional mode */
};

/* tdm_process_mode used for testing the tdm device in normal mode or internal
 * loopback or external loopback
 */
enum tdm_process_mode {
	e_TDM_PROCESS_NORMAL = 0	/* Normal mode */
	, e_TDM_PROCESS_INT_LPB = 1	/* Internal loop mode */
	, e_TDM_PROCESS_EXT_LPB = 2	/* External Loopback mode */
};


/* TDM configuration parameters */
struct fsl_tdm_adapt_cfg {
	u8 num_ch;		/* Number of channels in this adpater */
	u8 ch_size_type;		/* reciever/transmit channel
						size for all channels */
	u8 slot_width;		/* 1 or 2 Is defined by channel type */
	u8 frame_len;		/* Length of frame in samples */
	u32 num_frames;
	u8 loopback;			/* loopback or normal */
	u8 adap_mode;			/* 0=None, 1= T1, 2= T1-FULL, 3=E1,
						4 = E1-FULL */
	int max_num_ports;		/* Not Used: Max Number of ports that
					can be created on this adapter */
	int max_timeslots;		/* Max Number of timeslots that are
					supported on this adapter */
};

/*
 * tdm_adapter is the structure used to identify a physical tdm device along
 * with the access algorithms necessary to access it.
 */
struct tdm_adapter {
	struct module *owner;	/* owner of the adapter module */
	unsigned int id;	/* Adapter Id */
	unsigned int class;	/* classes to allow probing for */
	unsigned int drv_count;	/* Number of drivers associated with the
				 adapter */

	const struct tdm_adapt_algorithm *algo;	/* the algorithm to access the
						 adapter*/

	char name[TDM_NAME_SIZE];	/* Name of Adapter */
	struct mutex adap_lock;
	struct device *parent;		/*Not Used*/

	struct tasklet_struct tdm_data_tasklet;	/* tasklet handle to perform
						 data processing*/
	int tasklet_conf;	/* flag for tasklet configuration */
	int tdm_rx_flag;

	struct list_head myports;	/* list of ports, created on this
					 adapter */
	struct list_head list;
	spinlock_t portlist_lock;	/* Spin Lock for port_list */
	void *data;
	struct fsl_tdm_adapt_cfg adapt_cfg;
};

static inline void *tdm_get_adapdata(const struct tdm_adapter *dev)
{
	return dev->data;
}

static inline void tdm_set_adapdata(struct tdm_adapter *dev, void *data)
{
	dev->data = data;
}

/* functions exported by tdm.o */

extern int tdm_add_adapter(struct tdm_adapter *);
extern int tdm_del_adapter(struct tdm_adapter *);
extern int tdm_register_driver(struct tdm_driver *);
extern void tdm_del_driver(struct tdm_driver *);
extern void tdm_unregister_driver(struct tdm_driver *);
extern void init_config_adapter(struct tdm_adapter *);
extern int tdm_adap_enable(struct tdm_driver *drv);
extern int tdm_adap_disable(struct tdm_driver *drv);
extern unsigned int tdm_port_open(struct tdm_driver *, void **);
extern unsigned int tdm_port_close(void *);
extern unsigned int tdm_port_ioctl(void *, unsigned int, unsigned long);
extern unsigned int tdm_channel_read(void *, void *, void *, u16 *);
extern unsigned int tdm_channel_write(void *, void * , void *, u16);
extern unsigned int tdm_ch_poll(void *, unsigned int);

extern int tdm_channel_open(u16, u16, struct tdm_port *, void **);
extern int tdm_channel_close(u16, u16, struct tdm_port *,
						struct tdm_channel *);

static inline int tdm_add_driver(struct tdm_driver *driver)
{
	return tdm_register_driver(driver);
}

extern struct tdm_adapter *tdm_get_adapter(int id);
extern void tdm_put_adapter(struct tdm_adapter *adap);

#endif /* __KERNEL__ */

#define TDM_E_OK 0

#endif /* _LINUX_TDM_H */