xref: /linux/drivers/isdn/mISDN/dsp_tones.c (revision 960366cf8dbb3359afaca30cf7fdbf69a6d6dda7)
1*960366cfSKarsten Keil /*
2*960366cfSKarsten Keil  * Audio support data for ISDN4Linux.
3*960366cfSKarsten Keil  *
4*960366cfSKarsten Keil  * Copyright Andreas Eversberg (jolly@eversberg.eu)
5*960366cfSKarsten Keil  *
6*960366cfSKarsten Keil  * This software may be used and distributed according to the terms
7*960366cfSKarsten Keil  * of the GNU General Public License, incorporated herein by reference.
8*960366cfSKarsten Keil  *
9*960366cfSKarsten Keil  */
10*960366cfSKarsten Keil 
11*960366cfSKarsten Keil #include <linux/mISDNif.h>
12*960366cfSKarsten Keil #include <linux/mISDNdsp.h>
13*960366cfSKarsten Keil #include "core.h"
14*960366cfSKarsten Keil #include "dsp.h"
15*960366cfSKarsten Keil 
16*960366cfSKarsten Keil 
17*960366cfSKarsten Keil #define DATA_S sample_silence
18*960366cfSKarsten Keil #define SIZE_S (&sizeof_silence)
19*960366cfSKarsten Keil #define DATA_GA sample_german_all
20*960366cfSKarsten Keil #define SIZE_GA (&sizeof_german_all)
21*960366cfSKarsten Keil #define DATA_GO sample_german_old
22*960366cfSKarsten Keil #define SIZE_GO (&sizeof_german_old)
23*960366cfSKarsten Keil #define DATA_DT sample_american_dialtone
24*960366cfSKarsten Keil #define SIZE_DT (&sizeof_american_dialtone)
25*960366cfSKarsten Keil #define DATA_RI sample_american_ringing
26*960366cfSKarsten Keil #define SIZE_RI (&sizeof_american_ringing)
27*960366cfSKarsten Keil #define DATA_BU sample_american_busy
28*960366cfSKarsten Keil #define SIZE_BU (&sizeof_american_busy)
29*960366cfSKarsten Keil #define DATA_S1 sample_special1
30*960366cfSKarsten Keil #define SIZE_S1 (&sizeof_special1)
31*960366cfSKarsten Keil #define DATA_S2 sample_special2
32*960366cfSKarsten Keil #define SIZE_S2 (&sizeof_special2)
33*960366cfSKarsten Keil #define DATA_S3 sample_special3
34*960366cfSKarsten Keil #define SIZE_S3 (&sizeof_special3)
35*960366cfSKarsten Keil 
36*960366cfSKarsten Keil /***************/
37*960366cfSKarsten Keil /* tones loops */
38*960366cfSKarsten Keil /***************/
39*960366cfSKarsten Keil 
40*960366cfSKarsten Keil /* all tones are alaw encoded */
41*960366cfSKarsten Keil /* the last sample+1 is in phase with the first sample. the error is low */
42*960366cfSKarsten Keil 
43*960366cfSKarsten Keil static u8 sample_german_all[] = {
44*960366cfSKarsten Keil 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
45*960366cfSKarsten Keil 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
46*960366cfSKarsten Keil 	0xdc, 0xfc, 0x6c,
47*960366cfSKarsten Keil 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
48*960366cfSKarsten Keil 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
49*960366cfSKarsten Keil 	0xdc, 0xfc, 0x6c,
50*960366cfSKarsten Keil 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
51*960366cfSKarsten Keil 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
52*960366cfSKarsten Keil 	0xdc, 0xfc, 0x6c,
53*960366cfSKarsten Keil 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
54*960366cfSKarsten Keil 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
55*960366cfSKarsten Keil 	0xdc, 0xfc, 0x6c,
56*960366cfSKarsten Keil };
57*960366cfSKarsten Keil static u32 sizeof_german_all = sizeof(sample_german_all);
58*960366cfSKarsten Keil 
59*960366cfSKarsten Keil static u8 sample_german_old[] = {
60*960366cfSKarsten Keil 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
61*960366cfSKarsten Keil 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
62*960366cfSKarsten Keil 	0x8c,
63*960366cfSKarsten Keil 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
64*960366cfSKarsten Keil 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
65*960366cfSKarsten Keil 	0x8c,
66*960366cfSKarsten Keil 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
67*960366cfSKarsten Keil 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
68*960366cfSKarsten Keil 	0x8c,
69*960366cfSKarsten Keil 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
70*960366cfSKarsten Keil 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
71*960366cfSKarsten Keil 	0x8c,
72*960366cfSKarsten Keil };
73*960366cfSKarsten Keil static u32 sizeof_german_old = sizeof(sample_german_old);
74*960366cfSKarsten Keil 
75*960366cfSKarsten Keil static u8 sample_american_dialtone[] = {
76*960366cfSKarsten Keil 	0x2a, 0x18, 0x90, 0x6c, 0x4c, 0xbc, 0x4c, 0x6c,
77*960366cfSKarsten Keil 	0x10, 0x58, 0x32, 0xb9, 0x31, 0x2d, 0x8d, 0x0d,
78*960366cfSKarsten Keil 	0x8d, 0x2d, 0x31, 0x99, 0x0f, 0x28, 0x60, 0xf0,
79*960366cfSKarsten Keil 	0xd0, 0x50, 0xd0, 0x30, 0x60, 0x08, 0x8e, 0x67,
80*960366cfSKarsten Keil 	0x09, 0x19, 0x21, 0xe1, 0xd9, 0xb9, 0x29, 0x67,
81*960366cfSKarsten Keil 	0x83, 0x02, 0xce, 0xbe, 0xee, 0x1a, 0x1b, 0xef,
82*960366cfSKarsten Keil 	0xbf, 0xcf, 0x03, 0x82, 0x66, 0x28, 0xb8, 0xd8,
83*960366cfSKarsten Keil 	0xe0, 0x20, 0x18, 0x08, 0x66, 0x8f, 0x09, 0x61,
84*960366cfSKarsten Keil 	0x31, 0xd1, 0x51, 0xd1, 0xf1, 0x61, 0x29, 0x0e,
85*960366cfSKarsten Keil 	0x98, 0x30, 0x2c, 0x8c, 0x0c, 0x8c, 0x2c, 0x30,
86*960366cfSKarsten Keil 	0xb8, 0x33, 0x59, 0x11, 0x6d, 0x4d, 0xbd, 0x4d,
87*960366cfSKarsten Keil 	0x6d, 0x91, 0x19,
88*960366cfSKarsten Keil };
89*960366cfSKarsten Keil static u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
90*960366cfSKarsten Keil 
91*960366cfSKarsten Keil static u8 sample_american_ringing[] = {
92*960366cfSKarsten Keil 	0x2a, 0xe0, 0xac, 0x0c, 0xbc, 0x4c, 0x8c, 0x90,
93*960366cfSKarsten Keil 	0x48, 0xc7, 0xc1, 0xed, 0xcd, 0x4d, 0xcd, 0xed,
94*960366cfSKarsten Keil 	0xc1, 0xb7, 0x08, 0x30, 0xec, 0xcc, 0xcc, 0x8c,
95*960366cfSKarsten Keil 	0x10, 0x58, 0x1a, 0x99, 0x71, 0xed, 0x8d, 0x8d,
96*960366cfSKarsten Keil 	0x2d, 0x41, 0x89, 0x9e, 0x20, 0x70, 0x2c, 0xec,
97*960366cfSKarsten Keil 	0x2c, 0x70, 0x20, 0x86, 0x77, 0xe1, 0x31, 0x11,
98*960366cfSKarsten Keil 	0xd1, 0xf1, 0x81, 0x09, 0xa3, 0x56, 0x58, 0x00,
99*960366cfSKarsten Keil 	0x40, 0xc0, 0x60, 0x38, 0x46, 0x43, 0x57, 0x39,
100*960366cfSKarsten Keil 	0xd9, 0x59, 0x99, 0xc9, 0x77, 0x2f, 0x2e, 0xc6,
101*960366cfSKarsten Keil 	0xd6, 0x28, 0xd6, 0x36, 0x26, 0x2e, 0x8a, 0xa3,
102*960366cfSKarsten Keil 	0x43, 0x63, 0x4b, 0x4a, 0x62, 0x42, 0xa2, 0x8b,
103*960366cfSKarsten Keil 	0x2f, 0x27, 0x37, 0xd7, 0x29, 0xd7, 0xc7, 0x2f,
104*960366cfSKarsten Keil 	0x2e, 0x76, 0xc8, 0x98, 0x58, 0xd8, 0x38, 0x56,
105*960366cfSKarsten Keil 	0x42, 0x47, 0x39, 0x61, 0xc1, 0x41, 0x01, 0x59,
106*960366cfSKarsten Keil 	0x57, 0xa2, 0x08, 0x80, 0xf0, 0xd0, 0x10, 0x30,
107*960366cfSKarsten Keil 	0xe0, 0x76, 0x87, 0x21, 0x71, 0x2d, 0xed, 0x2d,
108*960366cfSKarsten Keil 	0x71, 0x21, 0x9f, 0x88, 0x40, 0x2c, 0x8c, 0x8c,
109*960366cfSKarsten Keil 	0xec, 0x70, 0x98, 0x1b, 0x59, 0x11, 0x8d, 0xcd,
110*960366cfSKarsten Keil 	0xcd, 0xed, 0x31, 0x09, 0xb6, 0xc0, 0xec, 0xcc,
111*960366cfSKarsten Keil 	0x4c, 0xcc, 0xec, 0xc0, 0xc6, 0x49, 0x91, 0x8d,
112*960366cfSKarsten Keil 	0x4d, 0xbd, 0x0d, 0xad, 0xe1,
113*960366cfSKarsten Keil };
114*960366cfSKarsten Keil static u32 sizeof_american_ringing = sizeof(sample_american_ringing);
115*960366cfSKarsten Keil 
116*960366cfSKarsten Keil static u8 sample_american_busy[] = {
117*960366cfSKarsten Keil 	0x2a, 0x00, 0x6c, 0x4c, 0x4c, 0x6c, 0xb0, 0x66,
118*960366cfSKarsten Keil 	0x99, 0x11, 0x6d, 0x8d, 0x2d, 0x41, 0xd7, 0x96,
119*960366cfSKarsten Keil 	0x60, 0xf0, 0x70, 0x40, 0x58, 0xf6, 0x53, 0x57,
120*960366cfSKarsten Keil 	0x09, 0x89, 0xd7, 0x5f, 0xe3, 0x2a, 0xe3, 0x5f,
121*960366cfSKarsten Keil 	0xd7, 0x89, 0x09, 0x57, 0x53, 0xf6, 0x58, 0x40,
122*960366cfSKarsten Keil 	0x70, 0xf0, 0x60, 0x96, 0xd7, 0x41, 0x2d, 0x8d,
123*960366cfSKarsten Keil 	0x6d, 0x11, 0x99, 0x66, 0xb0, 0x6c, 0x4c, 0x4c,
124*960366cfSKarsten Keil 	0x6c, 0x00, 0x2a, 0x01, 0x6d, 0x4d, 0x4d, 0x6d,
125*960366cfSKarsten Keil 	0xb1, 0x67, 0x98, 0x10, 0x6c, 0x8c, 0x2c, 0x40,
126*960366cfSKarsten Keil 	0xd6, 0x97, 0x61, 0xf1, 0x71, 0x41, 0x59, 0xf7,
127*960366cfSKarsten Keil 	0x52, 0x56, 0x08, 0x88, 0xd6, 0x5e, 0xe2, 0x2a,
128*960366cfSKarsten Keil 	0xe2, 0x5e, 0xd6, 0x88, 0x08, 0x56, 0x52, 0xf7,
129*960366cfSKarsten Keil 	0x59, 0x41, 0x71, 0xf1, 0x61, 0x97, 0xd6, 0x40,
130*960366cfSKarsten Keil 	0x2c, 0x8c, 0x6c, 0x10, 0x98, 0x67, 0xb1, 0x6d,
131*960366cfSKarsten Keil 	0x4d, 0x4d, 0x6d, 0x01,
132*960366cfSKarsten Keil };
133*960366cfSKarsten Keil static u32 sizeof_american_busy = sizeof(sample_american_busy);
134*960366cfSKarsten Keil 
135*960366cfSKarsten Keil static u8 sample_special1[] = {
136*960366cfSKarsten Keil 	0x2a, 0x2c, 0xbc, 0x6c, 0xd6, 0x71, 0xbd, 0x0d,
137*960366cfSKarsten Keil 	0xd9, 0x80, 0xcc, 0x4c, 0x40, 0x39, 0x0d, 0xbd,
138*960366cfSKarsten Keil 	0x11, 0x86, 0xec, 0xbc, 0xec, 0x0e, 0x51, 0xbd,
139*960366cfSKarsten Keil 	0x8d, 0x89, 0x30, 0x4c, 0xcc, 0xe0, 0xe1, 0xcd,
140*960366cfSKarsten Keil 	0x4d, 0x31, 0x88, 0x8c, 0xbc, 0x50, 0x0f, 0xed,
141*960366cfSKarsten Keil 	0xbd, 0xed, 0x87, 0x10, 0xbc, 0x0c, 0x38, 0x41,
142*960366cfSKarsten Keil 	0x4d, 0xcd, 0x81, 0xd8, 0x0c, 0xbc, 0x70, 0xd7,
143*960366cfSKarsten Keil 	0x6d, 0xbd, 0x2d,
144*960366cfSKarsten Keil };
145*960366cfSKarsten Keil static u32 sizeof_special1 = sizeof(sample_special1);
146*960366cfSKarsten Keil 
147*960366cfSKarsten Keil static u8 sample_special2[] = {
148*960366cfSKarsten Keil 	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
149*960366cfSKarsten Keil 	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
150*960366cfSKarsten Keil 	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
151*960366cfSKarsten Keil 	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
152*960366cfSKarsten Keil 	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
153*960366cfSKarsten Keil 	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
154*960366cfSKarsten Keil 	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
155*960366cfSKarsten Keil 	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
156*960366cfSKarsten Keil 	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
157*960366cfSKarsten Keil 	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
158*960366cfSKarsten Keil };
159*960366cfSKarsten Keil static u32 sizeof_special2 = sizeof(sample_special2);
160*960366cfSKarsten Keil 
161*960366cfSKarsten Keil static u8 sample_special3[] = {
162*960366cfSKarsten Keil 	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
163*960366cfSKarsten Keil 	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
164*960366cfSKarsten Keil 	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
165*960366cfSKarsten Keil 	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
166*960366cfSKarsten Keil 	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
167*960366cfSKarsten Keil 	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
168*960366cfSKarsten Keil 	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
169*960366cfSKarsten Keil 	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
170*960366cfSKarsten Keil 	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
171*960366cfSKarsten Keil 	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
172*960366cfSKarsten Keil };
173*960366cfSKarsten Keil static u32 sizeof_special3 = sizeof(sample_special3);
174*960366cfSKarsten Keil 
175*960366cfSKarsten Keil static u8 sample_silence[] = {
176*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
177*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
178*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
179*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
180*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
181*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
182*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
183*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
184*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
185*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
186*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
187*960366cfSKarsten Keil 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
188*960366cfSKarsten Keil };
189*960366cfSKarsten Keil static u32 sizeof_silence = sizeof(sample_silence);
190*960366cfSKarsten Keil 
191*960366cfSKarsten Keil struct tones_samples {
192*960366cfSKarsten Keil 	u32 *len;
193*960366cfSKarsten Keil 	u8 *data;
194*960366cfSKarsten Keil };
195*960366cfSKarsten Keil static struct
196*960366cfSKarsten Keil tones_samples samples[] = {
197*960366cfSKarsten Keil 	{&sizeof_german_all, sample_german_all},
198*960366cfSKarsten Keil 	{&sizeof_german_old, sample_german_old},
199*960366cfSKarsten Keil 	{&sizeof_american_dialtone, sample_american_dialtone},
200*960366cfSKarsten Keil 	{&sizeof_american_ringing, sample_american_ringing},
201*960366cfSKarsten Keil 	{&sizeof_american_busy, sample_american_busy},
202*960366cfSKarsten Keil 	{&sizeof_special1, sample_special1},
203*960366cfSKarsten Keil 	{&sizeof_special2, sample_special2},
204*960366cfSKarsten Keil 	{&sizeof_special3, sample_special3},
205*960366cfSKarsten Keil 	{NULL, NULL},
206*960366cfSKarsten Keil };
207*960366cfSKarsten Keil 
208*960366cfSKarsten Keil /***********************************
209*960366cfSKarsten Keil  * generate ulaw from alaw samples *
210*960366cfSKarsten Keil  ***********************************/
211*960366cfSKarsten Keil 
212*960366cfSKarsten Keil void
213*960366cfSKarsten Keil dsp_audio_generate_ulaw_samples(void)
214*960366cfSKarsten Keil {
215*960366cfSKarsten Keil 	int i, j;
216*960366cfSKarsten Keil 
217*960366cfSKarsten Keil 	i = 0;
218*960366cfSKarsten Keil 	while (samples[i].len) {
219*960366cfSKarsten Keil 		j = 0;
220*960366cfSKarsten Keil 		while (j < (*samples[i].len)) {
221*960366cfSKarsten Keil 			samples[i].data[j] =
222*960366cfSKarsten Keil 				dsp_audio_alaw_to_ulaw[samples[i].data[j]];
223*960366cfSKarsten Keil 			j++;
224*960366cfSKarsten Keil 		}
225*960366cfSKarsten Keil 		i++;
226*960366cfSKarsten Keil 	}
227*960366cfSKarsten Keil }
228*960366cfSKarsten Keil 
229*960366cfSKarsten Keil 
230*960366cfSKarsten Keil /****************************
231*960366cfSKarsten Keil  * tone sequence definition *
232*960366cfSKarsten Keil  ****************************/
233*960366cfSKarsten Keil 
234*960366cfSKarsten Keil struct pattern {
235*960366cfSKarsten Keil 	int tone;
236*960366cfSKarsten Keil 	u8 *data[10];
237*960366cfSKarsten Keil 	u32 *siz[10];
238*960366cfSKarsten Keil 	u32 seq[10];
239*960366cfSKarsten Keil } pattern[] = {
240*960366cfSKarsten Keil 	{TONE_GERMAN_DIALTONE,
241*960366cfSKarsten Keil 	{DATA_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0},
242*960366cfSKarsten Keil 	{SIZE_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0},
243*960366cfSKarsten Keil 	{1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
244*960366cfSKarsten Keil 
245*960366cfSKarsten Keil 	{TONE_GERMAN_OLDDIALTONE,
246*960366cfSKarsten Keil 	{DATA_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0},
247*960366cfSKarsten Keil 	{SIZE_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0},
248*960366cfSKarsten Keil 	{1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
249*960366cfSKarsten Keil 
250*960366cfSKarsten Keil 	{TONE_AMERICAN_DIALTONE,
251*960366cfSKarsten Keil 	{DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
252*960366cfSKarsten Keil 	{SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
253*960366cfSKarsten Keil 	{8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
254*960366cfSKarsten Keil 
255*960366cfSKarsten Keil 	{TONE_GERMAN_DIALPBX,
256*960366cfSKarsten Keil 	{DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0},
257*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0},
258*960366cfSKarsten Keil 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
259*960366cfSKarsten Keil 
260*960366cfSKarsten Keil 	{TONE_GERMAN_OLDDIALPBX,
261*960366cfSKarsten Keil 	{DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0},
262*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0},
263*960366cfSKarsten Keil 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
264*960366cfSKarsten Keil 
265*960366cfSKarsten Keil 	{TONE_AMERICAN_DIALPBX,
266*960366cfSKarsten Keil 	{DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, 0, 0, 0, 0},
267*960366cfSKarsten Keil 	{SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, 0, 0, 0, 0},
268*960366cfSKarsten Keil 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
269*960366cfSKarsten Keil 
270*960366cfSKarsten Keil 	{TONE_GERMAN_RINGING,
271*960366cfSKarsten Keil 	{DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
272*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
273*960366cfSKarsten Keil 	{8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
274*960366cfSKarsten Keil 
275*960366cfSKarsten Keil 	{TONE_GERMAN_OLDRINGING,
276*960366cfSKarsten Keil 	{DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
277*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
278*960366cfSKarsten Keil 	{8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} },
279*960366cfSKarsten Keil 
280*960366cfSKarsten Keil 	{TONE_AMERICAN_RINGING,
281*960366cfSKarsten Keil 	{DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
282*960366cfSKarsten Keil 	{SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
283*960366cfSKarsten Keil 	{8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
284*960366cfSKarsten Keil 
285*960366cfSKarsten Keil 	{TONE_GERMAN_RINGPBX,
286*960366cfSKarsten Keil 	{DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0},
287*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0},
288*960366cfSKarsten Keil 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
289*960366cfSKarsten Keil 
290*960366cfSKarsten Keil 	{TONE_GERMAN_OLDRINGPBX,
291*960366cfSKarsten Keil 	{DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0},
292*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0},
293*960366cfSKarsten Keil 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
294*960366cfSKarsten Keil 
295*960366cfSKarsten Keil 	{TONE_AMERICAN_RINGPBX,
296*960366cfSKarsten Keil 	{DATA_RI, DATA_S, DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0},
297*960366cfSKarsten Keil 	{SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0},
298*960366cfSKarsten Keil 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
299*960366cfSKarsten Keil 
300*960366cfSKarsten Keil 	{TONE_GERMAN_BUSY,
301*960366cfSKarsten Keil 	{DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
302*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
303*960366cfSKarsten Keil 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
304*960366cfSKarsten Keil 
305*960366cfSKarsten Keil 	{TONE_GERMAN_OLDBUSY,
306*960366cfSKarsten Keil 	{DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
307*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
308*960366cfSKarsten Keil 	{1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
309*960366cfSKarsten Keil 
310*960366cfSKarsten Keil 	{TONE_AMERICAN_BUSY,
311*960366cfSKarsten Keil 	{DATA_BU, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
312*960366cfSKarsten Keil 	{SIZE_BU, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
313*960366cfSKarsten Keil 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
314*960366cfSKarsten Keil 
315*960366cfSKarsten Keil 	{TONE_GERMAN_HANGUP,
316*960366cfSKarsten Keil 	{DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
317*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
318*960366cfSKarsten Keil 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
319*960366cfSKarsten Keil 
320*960366cfSKarsten Keil 	{TONE_GERMAN_OLDHANGUP,
321*960366cfSKarsten Keil 	{DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
322*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
323*960366cfSKarsten Keil 	{1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
324*960366cfSKarsten Keil 
325*960366cfSKarsten Keil 	{TONE_AMERICAN_HANGUP,
326*960366cfSKarsten Keil 	{DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
327*960366cfSKarsten Keil 	{SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0},
328*960366cfSKarsten Keil 	{8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
329*960366cfSKarsten Keil 
330*960366cfSKarsten Keil 	{TONE_SPECIAL_INFO,
331*960366cfSKarsten Keil 	{DATA_S1, DATA_S2, DATA_S3, DATA_S, 0, 0, 0, 0, 0, 0},
332*960366cfSKarsten Keil 	{SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, 0, 0, 0, 0, 0, 0},
333*960366cfSKarsten Keil 	{2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} },
334*960366cfSKarsten Keil 
335*960366cfSKarsten Keil 	{TONE_GERMAN_GASSENBESETZT,
336*960366cfSKarsten Keil 	{DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0},
337*960366cfSKarsten Keil 	{SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0},
338*960366cfSKarsten Keil 	{2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0} },
339*960366cfSKarsten Keil 
340*960366cfSKarsten Keil 	{TONE_GERMAN_AUFSCHALTTON,
341*960366cfSKarsten Keil 	{DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0},
342*960366cfSKarsten Keil 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0},
343*960366cfSKarsten Keil 	{1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} },
344*960366cfSKarsten Keil 
345*960366cfSKarsten Keil 	{0,
346*960366cfSKarsten Keil 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
347*960366cfSKarsten Keil 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
348*960366cfSKarsten Keil 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
349*960366cfSKarsten Keil };
350*960366cfSKarsten Keil 
351*960366cfSKarsten Keil /******************
352*960366cfSKarsten Keil  * copy tone data *
353*960366cfSKarsten Keil  ******************/
354*960366cfSKarsten Keil 
355*960366cfSKarsten Keil /* an sk_buff is generated from the number of samples needed.
356*960366cfSKarsten Keil  * the count will be changed and may begin from 0 each pattern period.
357*960366cfSKarsten Keil  * the clue is to precalculate the pointers and legths to use only one
358*960366cfSKarsten Keil  * memcpy per function call, or two memcpy if the tone sequence changes.
359*960366cfSKarsten Keil  *
360*960366cfSKarsten Keil  * pattern - the type of the pattern
361*960366cfSKarsten Keil  * count - the sample from the beginning of the pattern (phase)
362*960366cfSKarsten Keil  * len - the number of bytes
363*960366cfSKarsten Keil  *
364*960366cfSKarsten Keil  * return - the sk_buff with the sample
365*960366cfSKarsten Keil  *
366*960366cfSKarsten Keil  * if tones has finished (e.g. knocking tone), dsp->tones is turned off
367*960366cfSKarsten Keil  */
368*960366cfSKarsten Keil void dsp_tone_copy(struct dsp *dsp, u8 *data, int len)
369*960366cfSKarsten Keil {
370*960366cfSKarsten Keil 	int index, count, start, num;
371*960366cfSKarsten Keil 	struct pattern *pat;
372*960366cfSKarsten Keil 	struct dsp_tone *tone = &dsp->tone;
373*960366cfSKarsten Keil 
374*960366cfSKarsten Keil 	/* if we have no tone, we copy silence */
375*960366cfSKarsten Keil 	if (!tone->tone) {
376*960366cfSKarsten Keil 		memset(data, dsp_silence, len);
377*960366cfSKarsten Keil 		return;
378*960366cfSKarsten Keil 	}
379*960366cfSKarsten Keil 
380*960366cfSKarsten Keil 	/* process pattern */
381*960366cfSKarsten Keil 	pat = (struct pattern *)tone->pattern;
382*960366cfSKarsten Keil 		/* points to the current pattern */
383*960366cfSKarsten Keil 	index = tone->index; /* gives current sequence index */
384*960366cfSKarsten Keil 	count = tone->count; /* gives current sample */
385*960366cfSKarsten Keil 
386*960366cfSKarsten Keil 	/* copy sample */
387*960366cfSKarsten Keil 	while (len) {
388*960366cfSKarsten Keil 		/* find sample to start with */
389*960366cfSKarsten Keil 		while (42) {
390*960366cfSKarsten Keil 			/* warp arround */
391*960366cfSKarsten Keil 			if (!pat->seq[index]) {
392*960366cfSKarsten Keil 				count = 0;
393*960366cfSKarsten Keil 				index = 0;
394*960366cfSKarsten Keil 			}
395*960366cfSKarsten Keil 			/* check if we are currently playing this tone */
396*960366cfSKarsten Keil 			if (count < pat->seq[index])
397*960366cfSKarsten Keil 				break;
398*960366cfSKarsten Keil 			if (dsp_debug & DEBUG_DSP_TONE)
399*960366cfSKarsten Keil 				printk(KERN_DEBUG "%s: reaching next sequence "
400*960366cfSKarsten Keil 					"(index=%d)\n", __func__, index);
401*960366cfSKarsten Keil 			count -= pat->seq[index];
402*960366cfSKarsten Keil 			index++;
403*960366cfSKarsten Keil 		}
404*960366cfSKarsten Keil 		/* calculate start and number of samples */
405*960366cfSKarsten Keil 		start = count % (*(pat->siz[index]));
406*960366cfSKarsten Keil 		num = len;
407*960366cfSKarsten Keil 		if (num+count > pat->seq[index])
408*960366cfSKarsten Keil 			num = pat->seq[index] - count;
409*960366cfSKarsten Keil 		if (num+start > (*(pat->siz[index])))
410*960366cfSKarsten Keil 			num = (*(pat->siz[index])) - start;
411*960366cfSKarsten Keil 		/* copy memory */
412*960366cfSKarsten Keil 		memcpy(data, pat->data[index]+start, num);
413*960366cfSKarsten Keil 		/* reduce length */
414*960366cfSKarsten Keil 		data += num;
415*960366cfSKarsten Keil 		count += num;
416*960366cfSKarsten Keil 		len -= num;
417*960366cfSKarsten Keil 	}
418*960366cfSKarsten Keil 	tone->index = index;
419*960366cfSKarsten Keil 	tone->count = count;
420*960366cfSKarsten Keil 
421*960366cfSKarsten Keil 	/* return sk_buff */
422*960366cfSKarsten Keil 	return;
423*960366cfSKarsten Keil }
424*960366cfSKarsten Keil 
425*960366cfSKarsten Keil 
426*960366cfSKarsten Keil /*******************************
427*960366cfSKarsten Keil  * send HW message to hfc card *
428*960366cfSKarsten Keil  *******************************/
429*960366cfSKarsten Keil 
430*960366cfSKarsten Keil static void
431*960366cfSKarsten Keil dsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len)
432*960366cfSKarsten Keil {
433*960366cfSKarsten Keil 	struct sk_buff *nskb;
434*960366cfSKarsten Keil 
435*960366cfSKarsten Keil 	/* unlocking is not required, because we don't expect a response */
436*960366cfSKarsten Keil 	nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
437*960366cfSKarsten Keil 		(len)?HFC_SPL_LOOP_ON:HFC_SPL_LOOP_OFF, len, sample,
438*960366cfSKarsten Keil 		GFP_ATOMIC);
439*960366cfSKarsten Keil 	if (nskb) {
440*960366cfSKarsten Keil 		if (dsp->ch.peer) {
441*960366cfSKarsten Keil 			if (dsp->ch.recv(dsp->ch.peer, nskb))
442*960366cfSKarsten Keil 				dev_kfree_skb(nskb);
443*960366cfSKarsten Keil 		} else
444*960366cfSKarsten Keil 			dev_kfree_skb(nskb);
445*960366cfSKarsten Keil 	}
446*960366cfSKarsten Keil }
447*960366cfSKarsten Keil 
448*960366cfSKarsten Keil 
449*960366cfSKarsten Keil /*****************
450*960366cfSKarsten Keil  * timer expires *
451*960366cfSKarsten Keil  *****************/
452*960366cfSKarsten Keil void
453*960366cfSKarsten Keil dsp_tone_timeout(void *arg)
454*960366cfSKarsten Keil {
455*960366cfSKarsten Keil 	struct dsp *dsp = arg;
456*960366cfSKarsten Keil 	struct dsp_tone *tone = &dsp->tone;
457*960366cfSKarsten Keil 	struct pattern *pat = (struct pattern *)tone->pattern;
458*960366cfSKarsten Keil 	int index = tone->index;
459*960366cfSKarsten Keil 
460*960366cfSKarsten Keil 	if (!tone->tone)
461*960366cfSKarsten Keil 		return;
462*960366cfSKarsten Keil 
463*960366cfSKarsten Keil 	index++;
464*960366cfSKarsten Keil 	if (!pat->seq[index])
465*960366cfSKarsten Keil 		index = 0;
466*960366cfSKarsten Keil 	tone->index = index;
467*960366cfSKarsten Keil 
468*960366cfSKarsten Keil 	/* set next tone */
469*960366cfSKarsten Keil 	if (pat->data[index] == DATA_S)
470*960366cfSKarsten Keil 		dsp_tone_hw_message(dsp, 0, 0);
471*960366cfSKarsten Keil 	else
472*960366cfSKarsten Keil 		dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
473*960366cfSKarsten Keil 	/* set timer */
474*960366cfSKarsten Keil 	init_timer(&tone->tl);
475*960366cfSKarsten Keil 	tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
476*960366cfSKarsten Keil 	add_timer(&tone->tl);
477*960366cfSKarsten Keil }
478*960366cfSKarsten Keil 
479*960366cfSKarsten Keil 
480*960366cfSKarsten Keil /********************
481*960366cfSKarsten Keil  * set/release tone *
482*960366cfSKarsten Keil  ********************/
483*960366cfSKarsten Keil 
484*960366cfSKarsten Keil /*
485*960366cfSKarsten Keil  * tones are relaized by streaming or by special loop commands if supported
486*960366cfSKarsten Keil  * by hardware. when hardware is used, the patterns will be controlled by
487*960366cfSKarsten Keil  * timers.
488*960366cfSKarsten Keil  */
489*960366cfSKarsten Keil int
490*960366cfSKarsten Keil dsp_tone(struct dsp *dsp, int tone)
491*960366cfSKarsten Keil {
492*960366cfSKarsten Keil 	struct pattern *pat;
493*960366cfSKarsten Keil 	int i;
494*960366cfSKarsten Keil 	struct dsp_tone *tonet = &dsp->tone;
495*960366cfSKarsten Keil 
496*960366cfSKarsten Keil 	tonet->software = 0;
497*960366cfSKarsten Keil 	tonet->hardware = 0;
498*960366cfSKarsten Keil 
499*960366cfSKarsten Keil 	/* we turn off the tone */
500*960366cfSKarsten Keil 	if (!tone) {
501*960366cfSKarsten Keil 		if (dsp->features.hfc_loops)
502*960366cfSKarsten Keil 		if (timer_pending(&tonet->tl))
503*960366cfSKarsten Keil 			del_timer(&tonet->tl);
504*960366cfSKarsten Keil 		if (dsp->features.hfc_loops)
505*960366cfSKarsten Keil 			dsp_tone_hw_message(dsp, NULL, 0);
506*960366cfSKarsten Keil 		tonet->tone = 0;
507*960366cfSKarsten Keil 		return 0;
508*960366cfSKarsten Keil 	}
509*960366cfSKarsten Keil 
510*960366cfSKarsten Keil 	pat = NULL;
511*960366cfSKarsten Keil 	i = 0;
512*960366cfSKarsten Keil 	while (pattern[i].tone) {
513*960366cfSKarsten Keil 		if (pattern[i].tone == tone) {
514*960366cfSKarsten Keil 			pat = &pattern[i];
515*960366cfSKarsten Keil 			break;
516*960366cfSKarsten Keil 		}
517*960366cfSKarsten Keil 		i++;
518*960366cfSKarsten Keil 	}
519*960366cfSKarsten Keil 	if (!pat) {
520*960366cfSKarsten Keil 		printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
521*960366cfSKarsten Keil 		return -EINVAL;
522*960366cfSKarsten Keil 	}
523*960366cfSKarsten Keil 	if (dsp_debug & DEBUG_DSP_TONE)
524*960366cfSKarsten Keil 		printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n",
525*960366cfSKarsten Keil 			__func__, tone, 0);
526*960366cfSKarsten Keil 	tonet->tone = tone;
527*960366cfSKarsten Keil 	tonet->pattern = pat;
528*960366cfSKarsten Keil 	tonet->index = 0;
529*960366cfSKarsten Keil 	tonet->count = 0;
530*960366cfSKarsten Keil 
531*960366cfSKarsten Keil 	if (dsp->features.hfc_loops) {
532*960366cfSKarsten Keil 		tonet->hardware = 1;
533*960366cfSKarsten Keil 		/* set first tone */
534*960366cfSKarsten Keil 		dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0]));
535*960366cfSKarsten Keil 		/* set timer */
536*960366cfSKarsten Keil 		if (timer_pending(&tonet->tl))
537*960366cfSKarsten Keil 			del_timer(&tonet->tl);
538*960366cfSKarsten Keil 		init_timer(&tonet->tl);
539*960366cfSKarsten Keil 		tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
540*960366cfSKarsten Keil 		add_timer(&tonet->tl);
541*960366cfSKarsten Keil 	} else {
542*960366cfSKarsten Keil 		tonet->software = 1;
543*960366cfSKarsten Keil 	}
544*960366cfSKarsten Keil 
545*960366cfSKarsten Keil 	return 0;
546*960366cfSKarsten Keil }
547*960366cfSKarsten Keil 
548*960366cfSKarsten Keil 
549*960366cfSKarsten Keil 
550*960366cfSKarsten Keil 
551*960366cfSKarsten Keil 
552