874b76bd22
Allows the driver the option of not calling the misc function for every frame. This is part of preparation for moving misc processing out of the interrupt handler. Also use a state machine for the various battery states to unify the technique for debouncing the various signals in the driver. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10169 a0bf4364-ded3-4de4-8d8a-66a801d63aff
315 lines
7.4 KiB
C
315 lines
7.4 KiB
C
/*
|
|
* Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface
|
|
*
|
|
* Written by Mark Spencer <markster@digium.com>
|
|
* Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com>
|
|
*
|
|
* Copyright (C) 2005-2010 Digium, Inc.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2 as published by the
|
|
* Free Software Foundation. See the LICENSE file included with
|
|
* this program for more details.
|
|
*/
|
|
|
|
#ifndef _WCTDM24XXP_H
|
|
#define _WCTDM24XXP_H
|
|
|
|
#include <dahdi/kernel.h>
|
|
|
|
#include <linux/version.h>
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
|
#include <linux/semaphore.h>
|
|
#else
|
|
#include <asm/semaphore.h>
|
|
#endif
|
|
|
|
#include "voicebus/voicebus.h"
|
|
|
|
#define NUM_FXO_REGS 60
|
|
|
|
#define WC_MAX_IFACES 128
|
|
|
|
/*!
|
|
* \brief Default ringer debounce (in ms)
|
|
*/
|
|
#define DEFAULT_RING_DEBOUNCE 1024
|
|
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
|
|
|
|
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
|
|
|
#define FLAG_EXPRESS (1 << 0)
|
|
|
|
#define EFRAME_SIZE 108L
|
|
#define EFRAME_GAP 20L
|
|
#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1)))
|
|
|
|
#define MAX_ALARMS 10
|
|
|
|
#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */
|
|
#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */
|
|
#define PEGCOUNT 5 /* 5 cycles of pegging means RING */
|
|
|
|
#define SDI_CLK (0x00010000)
|
|
#define SDI_DOUT (0x00020000)
|
|
#define SDI_DREAD (0x00040000)
|
|
#define SDI_DIN (0x00080000)
|
|
|
|
#define __CMD_RD (1 << 20) /* Read Operation */
|
|
#define __CMD_WR (1 << 21) /* Write Operation */
|
|
#define __CMD_FIN (1 << 22) /* Has finished receive */
|
|
#define __CMD_TX (1 << 23) /* Has been transmitted */
|
|
|
|
#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
|
|
#define CMD_RD(a) (((a) << 8) | __CMD_RD)
|
|
|
|
#if 0
|
|
#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \
|
|
+ ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0))
|
|
#endif
|
|
#define NUM_MODULES 24
|
|
#define NUM_SLOTS 6
|
|
#define MAX_SPANS 9
|
|
|
|
#define NUM_CAL_REGS 12
|
|
|
|
#define QRV_DEBOUNCETIME 20
|
|
|
|
#define VPM150M_HPI_CONTROL 0x00
|
|
#define VPM150M_HPI_ADDRESS 0x02
|
|
#define VPM150M_HPI_DATA 0x03
|
|
|
|
#define VPM_SUPPORT
|
|
#define VPM150M_SUPPORT
|
|
|
|
#ifdef VPM150M_SUPPORT
|
|
#include "voicebus/GpakCust.h"
|
|
#endif
|
|
|
|
#include "voicebus/vpmoct.h"
|
|
|
|
struct calregs {
|
|
unsigned char vals[NUM_CAL_REGS];
|
|
};
|
|
|
|
enum battery_state {
|
|
BATTERY_UNKNOWN = 0,
|
|
BATTERY_DEBOUNCING_PRESENT,
|
|
BATTERY_DEBOUNCING_PRESENT_ALARM,
|
|
BATTERY_PRESENT,
|
|
BATTERY_DEBOUNCING_LOST,
|
|
BATTERY_DEBOUNCING_LOST_ALARM,
|
|
BATTERY_LOST,
|
|
};
|
|
|
|
enum ring_detector_state {
|
|
RINGOFF = 0,
|
|
DEBOUNCING_RINGING_POSITIVE,
|
|
DEBOUNCING_RINGING_NEGATIVE,
|
|
DEBOUNCING_RINGING_OFF,
|
|
RINGING,
|
|
DEBOUNCING_RINGOFF,
|
|
};
|
|
|
|
struct wctdm_cmd {
|
|
struct list_head node;
|
|
struct completion *complete;
|
|
u32 cmd;
|
|
u8 ident;
|
|
};
|
|
|
|
/**
|
|
* struct wctdm_span -
|
|
* @span: dahdi_span to register.
|
|
* @timing_priority: What the priority of this span is relative to the other
|
|
* spans.
|
|
* @spanno: Which span on the card this is.
|
|
*
|
|
* NOTE: spanno would normally be taken care of by dahdi_span.offset, but
|
|
* appears to have meaning in xhfc.c, and that needs to be audited before
|
|
* changing. !!!TODO!!!
|
|
*
|
|
*/
|
|
struct wctdm_span {
|
|
struct dahdi_span span;
|
|
int timing_priority;
|
|
int spanno;
|
|
struct wctdm *wc;
|
|
struct b400m_span *bspan;
|
|
};
|
|
|
|
struct wctdm_chan {
|
|
struct dahdi_chan chan;
|
|
struct dahdi_echocan_state ec;
|
|
int timeslot;
|
|
unsigned int hwpreec_enabled:1;
|
|
};
|
|
|
|
struct fxo {
|
|
enum ring_detector_state ring_state:4;
|
|
enum battery_state battery_state:4;
|
|
u8 ring_polarity_change_count:4;
|
|
u8 hook_ring_shadow;
|
|
s8 line_voltage_status;
|
|
int offhook;
|
|
int lastpol;
|
|
int polarity;
|
|
int polaritydebounce;
|
|
int neonmwi_state;
|
|
int neonmwi_last_voltage;
|
|
unsigned int neonmwi_debounce;
|
|
unsigned int neonmwi_offcounter;
|
|
unsigned long display_fxovoltage;
|
|
unsigned long ringdebounce_timer;
|
|
unsigned long battdebounce_timer;
|
|
};
|
|
|
|
struct fxs {
|
|
u8 oht_active:1;
|
|
u8 off_hook:1;
|
|
int idletxhookstate; /* IDLE changing hook state */
|
|
/* lasttxhook reflects the last value written to the proslic's reg
|
|
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
|
|
* write is pending i.e. it is in process of being written to the
|
|
* register
|
|
* NOTE: in order for this value to actually be written to the
|
|
* proslic, the appropriate matching value must be written into the
|
|
* sethook variable so that it gets queued and handled by the
|
|
* voicebus ISR.
|
|
*/
|
|
int lasttxhook;
|
|
u8 linefeed_control_shadow;
|
|
u8 hook_state_shadow;
|
|
int palarms;
|
|
struct dahdi_vmwi_info vmwisetting;
|
|
int vmwi_active_messages;
|
|
int vmwi_linereverse;
|
|
int reversepolarity; /* polarity reversal */
|
|
struct calregs calregs;
|
|
unsigned long check_alarm;
|
|
unsigned long check_proslic;
|
|
unsigned long oppending_timeout;
|
|
unsigned long ohttimer;
|
|
};
|
|
|
|
struct qrv {
|
|
#define RADMODE_INVERTCOR 1
|
|
#define RADMODE_IGNORECOR 2
|
|
#define RADMODE_EXTTONE 4
|
|
#define RADMODE_EXTINVERT 8
|
|
#define RADMODE_IGNORECT 16
|
|
#define RADMODE_PREEMP 32
|
|
#define RADMODE_DEEMP 64
|
|
char hook;
|
|
unsigned short debouncetime;
|
|
unsigned short debtime;
|
|
int radmode;
|
|
signed short rxgain;
|
|
signed short txgain;
|
|
u8 isrshadow[3];
|
|
};
|
|
|
|
enum module_type {
|
|
NONE = 0,
|
|
FXS,
|
|
FXO,
|
|
FXSINIT,
|
|
QRV,
|
|
BRI,
|
|
};
|
|
|
|
struct wctdm_module {
|
|
union modtypes {
|
|
struct fxo fxo;
|
|
struct fxs fxs;
|
|
struct qrv qrv;
|
|
struct b400m *bri;
|
|
} mod;
|
|
|
|
/* Protected by wctdm.reglock */
|
|
struct list_head pending_cmds;
|
|
struct list_head active_cmds;
|
|
u8 offsets[3];
|
|
u8 subaddr;
|
|
u8 card;
|
|
|
|
enum module_type type;
|
|
int sethook; /* pending hook state command */
|
|
int dacssrc;
|
|
};
|
|
|
|
struct wctdm {
|
|
const struct wctdm_desc *desc;
|
|
const char *board_name;
|
|
|
|
spinlock_t frame_list_lock;
|
|
struct list_head frame_list;
|
|
|
|
unsigned long framecount;
|
|
unsigned char txident;
|
|
unsigned char rxident;
|
|
|
|
u8 ctlreg;
|
|
u8 tdm410leds;
|
|
|
|
int mods_per_board; /* maximum number of modules for this board */
|
|
int digi_mods; /* number of digital modules present */
|
|
int avchannels; /* active "voice" (voice, B and D) channels */
|
|
|
|
spinlock_t reglock; /* held when accessing anything affecting the module array */
|
|
wait_queue_head_t regq;
|
|
struct list_head free_isr_commands;
|
|
|
|
struct wctdm_module mods[NUM_MODULES];
|
|
|
|
struct vpmadt032 *vpmadt032;
|
|
struct vpmoct *vpmoct;
|
|
struct voicebus vb;
|
|
struct wctdm_span *aspan; /* pointer to the spans[] holding the analog span */
|
|
struct wctdm_span *spans[MAX_SPANS];
|
|
struct wctdm_chan *chans[NUM_MODULES];
|
|
#ifdef CONFIG_VOICEBUS_ECREFERENCE
|
|
struct dahdi_fifo *ec_reference[NUM_MODULES];
|
|
#endif
|
|
|
|
/* Only care about digital spans here */
|
|
/* int span_timing_prio[MAX_SPANS - 1]; */
|
|
struct semaphore syncsem;
|
|
int oldsync;
|
|
|
|
int not_ready; /* 0 when the entire card is ready to go */
|
|
unsigned long checkflag; /* Internal state flags and task bits */
|
|
int companding;
|
|
};
|
|
|
|
static inline bool is_initialized(struct wctdm *wc)
|
|
{
|
|
WARN_ON(wc->not_ready < 0);
|
|
return (wc->not_ready == 0);
|
|
}
|
|
|
|
/* Atomic flag bits for checkflag field */
|
|
#define WCTDM_CHECK_TIMING 0
|
|
|
|
int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr);
|
|
int wctdm_setreg(struct wctdm *wc, struct wctdm_module *const mod,
|
|
int addr, int val);
|
|
|
|
int wctdm_wait_for_ready(struct wctdm *wc);
|
|
|
|
extern struct semaphore ifacelock;
|
|
extern struct wctdm *ifaces[WC_MAX_IFACES];
|
|
|
|
#endif
|