18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Audio support data for ISDN4Linux.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright Andreas Eversberg (jolly@eversberg.eu)
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This software may be used and distributed according to the terms
78c2ecf20Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/gfp.h>
128c2ecf20Sopenharmony_ci#include <linux/mISDNif.h>
138c2ecf20Sopenharmony_ci#include <linux/mISDNdsp.h>
148c2ecf20Sopenharmony_ci#include "core.h"
158c2ecf20Sopenharmony_ci#include "dsp.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define DATA_S sample_silence
198c2ecf20Sopenharmony_ci#define SIZE_S (&sizeof_silence)
208c2ecf20Sopenharmony_ci#define DATA_GA sample_german_all
218c2ecf20Sopenharmony_ci#define SIZE_GA (&sizeof_german_all)
228c2ecf20Sopenharmony_ci#define DATA_GO sample_german_old
238c2ecf20Sopenharmony_ci#define SIZE_GO (&sizeof_german_old)
248c2ecf20Sopenharmony_ci#define DATA_DT sample_american_dialtone
258c2ecf20Sopenharmony_ci#define SIZE_DT (&sizeof_american_dialtone)
268c2ecf20Sopenharmony_ci#define DATA_RI sample_american_ringing
278c2ecf20Sopenharmony_ci#define SIZE_RI (&sizeof_american_ringing)
288c2ecf20Sopenharmony_ci#define DATA_BU sample_american_busy
298c2ecf20Sopenharmony_ci#define SIZE_BU (&sizeof_american_busy)
308c2ecf20Sopenharmony_ci#define DATA_S1 sample_special1
318c2ecf20Sopenharmony_ci#define SIZE_S1 (&sizeof_special1)
328c2ecf20Sopenharmony_ci#define DATA_S2 sample_special2
338c2ecf20Sopenharmony_ci#define SIZE_S2 (&sizeof_special2)
348c2ecf20Sopenharmony_ci#define DATA_S3 sample_special3
358c2ecf20Sopenharmony_ci#define SIZE_S3 (&sizeof_special3)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/***************/
388c2ecf20Sopenharmony_ci/* tones loops */
398c2ecf20Sopenharmony_ci/***************/
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* all tones are alaw encoded */
428c2ecf20Sopenharmony_ci/* the last sample+1 is in phase with the first sample. the error is low */
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic u8 sample_german_all[] = {
458c2ecf20Sopenharmony_ci	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
468c2ecf20Sopenharmony_ci	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
478c2ecf20Sopenharmony_ci	0xdc, 0xfc, 0x6c,
488c2ecf20Sopenharmony_ci	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
498c2ecf20Sopenharmony_ci	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
508c2ecf20Sopenharmony_ci	0xdc, 0xfc, 0x6c,
518c2ecf20Sopenharmony_ci	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
528c2ecf20Sopenharmony_ci	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
538c2ecf20Sopenharmony_ci	0xdc, 0xfc, 0x6c,
548c2ecf20Sopenharmony_ci	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
558c2ecf20Sopenharmony_ci	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
568c2ecf20Sopenharmony_ci	0xdc, 0xfc, 0x6c,
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_cistatic u32 sizeof_german_all = sizeof(sample_german_all);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic u8 sample_german_old[] = {
618c2ecf20Sopenharmony_ci	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
628c2ecf20Sopenharmony_ci	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
638c2ecf20Sopenharmony_ci	0x8c,
648c2ecf20Sopenharmony_ci	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
658c2ecf20Sopenharmony_ci	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
668c2ecf20Sopenharmony_ci	0x8c,
678c2ecf20Sopenharmony_ci	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
688c2ecf20Sopenharmony_ci	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
698c2ecf20Sopenharmony_ci	0x8c,
708c2ecf20Sopenharmony_ci	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
718c2ecf20Sopenharmony_ci	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
728c2ecf20Sopenharmony_ci	0x8c,
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_cistatic u32 sizeof_german_old = sizeof(sample_german_old);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic u8 sample_american_dialtone[] = {
778c2ecf20Sopenharmony_ci	0x2a, 0x18, 0x90, 0x6c, 0x4c, 0xbc, 0x4c, 0x6c,
788c2ecf20Sopenharmony_ci	0x10, 0x58, 0x32, 0xb9, 0x31, 0x2d, 0x8d, 0x0d,
798c2ecf20Sopenharmony_ci	0x8d, 0x2d, 0x31, 0x99, 0x0f, 0x28, 0x60, 0xf0,
808c2ecf20Sopenharmony_ci	0xd0, 0x50, 0xd0, 0x30, 0x60, 0x08, 0x8e, 0x67,
818c2ecf20Sopenharmony_ci	0x09, 0x19, 0x21, 0xe1, 0xd9, 0xb9, 0x29, 0x67,
828c2ecf20Sopenharmony_ci	0x83, 0x02, 0xce, 0xbe, 0xee, 0x1a, 0x1b, 0xef,
838c2ecf20Sopenharmony_ci	0xbf, 0xcf, 0x03, 0x82, 0x66, 0x28, 0xb8, 0xd8,
848c2ecf20Sopenharmony_ci	0xe0, 0x20, 0x18, 0x08, 0x66, 0x8f, 0x09, 0x61,
858c2ecf20Sopenharmony_ci	0x31, 0xd1, 0x51, 0xd1, 0xf1, 0x61, 0x29, 0x0e,
868c2ecf20Sopenharmony_ci	0x98, 0x30, 0x2c, 0x8c, 0x0c, 0x8c, 0x2c, 0x30,
878c2ecf20Sopenharmony_ci	0xb8, 0x33, 0x59, 0x11, 0x6d, 0x4d, 0xbd, 0x4d,
888c2ecf20Sopenharmony_ci	0x6d, 0x91, 0x19,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_cistatic u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic u8 sample_american_ringing[] = {
938c2ecf20Sopenharmony_ci	0x2a, 0xe0, 0xac, 0x0c, 0xbc, 0x4c, 0x8c, 0x90,
948c2ecf20Sopenharmony_ci	0x48, 0xc7, 0xc1, 0xed, 0xcd, 0x4d, 0xcd, 0xed,
958c2ecf20Sopenharmony_ci	0xc1, 0xb7, 0x08, 0x30, 0xec, 0xcc, 0xcc, 0x8c,
968c2ecf20Sopenharmony_ci	0x10, 0x58, 0x1a, 0x99, 0x71, 0xed, 0x8d, 0x8d,
978c2ecf20Sopenharmony_ci	0x2d, 0x41, 0x89, 0x9e, 0x20, 0x70, 0x2c, 0xec,
988c2ecf20Sopenharmony_ci	0x2c, 0x70, 0x20, 0x86, 0x77, 0xe1, 0x31, 0x11,
998c2ecf20Sopenharmony_ci	0xd1, 0xf1, 0x81, 0x09, 0xa3, 0x56, 0x58, 0x00,
1008c2ecf20Sopenharmony_ci	0x40, 0xc0, 0x60, 0x38, 0x46, 0x43, 0x57, 0x39,
1018c2ecf20Sopenharmony_ci	0xd9, 0x59, 0x99, 0xc9, 0x77, 0x2f, 0x2e, 0xc6,
1028c2ecf20Sopenharmony_ci	0xd6, 0x28, 0xd6, 0x36, 0x26, 0x2e, 0x8a, 0xa3,
1038c2ecf20Sopenharmony_ci	0x43, 0x63, 0x4b, 0x4a, 0x62, 0x42, 0xa2, 0x8b,
1048c2ecf20Sopenharmony_ci	0x2f, 0x27, 0x37, 0xd7, 0x29, 0xd7, 0xc7, 0x2f,
1058c2ecf20Sopenharmony_ci	0x2e, 0x76, 0xc8, 0x98, 0x58, 0xd8, 0x38, 0x56,
1068c2ecf20Sopenharmony_ci	0x42, 0x47, 0x39, 0x61, 0xc1, 0x41, 0x01, 0x59,
1078c2ecf20Sopenharmony_ci	0x57, 0xa2, 0x08, 0x80, 0xf0, 0xd0, 0x10, 0x30,
1088c2ecf20Sopenharmony_ci	0xe0, 0x76, 0x87, 0x21, 0x71, 0x2d, 0xed, 0x2d,
1098c2ecf20Sopenharmony_ci	0x71, 0x21, 0x9f, 0x88, 0x40, 0x2c, 0x8c, 0x8c,
1108c2ecf20Sopenharmony_ci	0xec, 0x70, 0x98, 0x1b, 0x59, 0x11, 0x8d, 0xcd,
1118c2ecf20Sopenharmony_ci	0xcd, 0xed, 0x31, 0x09, 0xb6, 0xc0, 0xec, 0xcc,
1128c2ecf20Sopenharmony_ci	0x4c, 0xcc, 0xec, 0xc0, 0xc6, 0x49, 0x91, 0x8d,
1138c2ecf20Sopenharmony_ci	0x4d, 0xbd, 0x0d, 0xad, 0xe1,
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_cistatic u32 sizeof_american_ringing = sizeof(sample_american_ringing);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic u8 sample_american_busy[] = {
1188c2ecf20Sopenharmony_ci	0x2a, 0x00, 0x6c, 0x4c, 0x4c, 0x6c, 0xb0, 0x66,
1198c2ecf20Sopenharmony_ci	0x99, 0x11, 0x6d, 0x8d, 0x2d, 0x41, 0xd7, 0x96,
1208c2ecf20Sopenharmony_ci	0x60, 0xf0, 0x70, 0x40, 0x58, 0xf6, 0x53, 0x57,
1218c2ecf20Sopenharmony_ci	0x09, 0x89, 0xd7, 0x5f, 0xe3, 0x2a, 0xe3, 0x5f,
1228c2ecf20Sopenharmony_ci	0xd7, 0x89, 0x09, 0x57, 0x53, 0xf6, 0x58, 0x40,
1238c2ecf20Sopenharmony_ci	0x70, 0xf0, 0x60, 0x96, 0xd7, 0x41, 0x2d, 0x8d,
1248c2ecf20Sopenharmony_ci	0x6d, 0x11, 0x99, 0x66, 0xb0, 0x6c, 0x4c, 0x4c,
1258c2ecf20Sopenharmony_ci	0x6c, 0x00, 0x2a, 0x01, 0x6d, 0x4d, 0x4d, 0x6d,
1268c2ecf20Sopenharmony_ci	0xb1, 0x67, 0x98, 0x10, 0x6c, 0x8c, 0x2c, 0x40,
1278c2ecf20Sopenharmony_ci	0xd6, 0x97, 0x61, 0xf1, 0x71, 0x41, 0x59, 0xf7,
1288c2ecf20Sopenharmony_ci	0x52, 0x56, 0x08, 0x88, 0xd6, 0x5e, 0xe2, 0x2a,
1298c2ecf20Sopenharmony_ci	0xe2, 0x5e, 0xd6, 0x88, 0x08, 0x56, 0x52, 0xf7,
1308c2ecf20Sopenharmony_ci	0x59, 0x41, 0x71, 0xf1, 0x61, 0x97, 0xd6, 0x40,
1318c2ecf20Sopenharmony_ci	0x2c, 0x8c, 0x6c, 0x10, 0x98, 0x67, 0xb1, 0x6d,
1328c2ecf20Sopenharmony_ci	0x4d, 0x4d, 0x6d, 0x01,
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_cistatic u32 sizeof_american_busy = sizeof(sample_american_busy);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic u8 sample_special1[] = {
1378c2ecf20Sopenharmony_ci	0x2a, 0x2c, 0xbc, 0x6c, 0xd6, 0x71, 0xbd, 0x0d,
1388c2ecf20Sopenharmony_ci	0xd9, 0x80, 0xcc, 0x4c, 0x40, 0x39, 0x0d, 0xbd,
1398c2ecf20Sopenharmony_ci	0x11, 0x86, 0xec, 0xbc, 0xec, 0x0e, 0x51, 0xbd,
1408c2ecf20Sopenharmony_ci	0x8d, 0x89, 0x30, 0x4c, 0xcc, 0xe0, 0xe1, 0xcd,
1418c2ecf20Sopenharmony_ci	0x4d, 0x31, 0x88, 0x8c, 0xbc, 0x50, 0x0f, 0xed,
1428c2ecf20Sopenharmony_ci	0xbd, 0xed, 0x87, 0x10, 0xbc, 0x0c, 0x38, 0x41,
1438c2ecf20Sopenharmony_ci	0x4d, 0xcd, 0x81, 0xd8, 0x0c, 0xbc, 0x70, 0xd7,
1448c2ecf20Sopenharmony_ci	0x6d, 0xbd, 0x2d,
1458c2ecf20Sopenharmony_ci};
1468c2ecf20Sopenharmony_cistatic u32 sizeof_special1 = sizeof(sample_special1);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic u8 sample_special2[] = {
1498c2ecf20Sopenharmony_ci	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
1508c2ecf20Sopenharmony_ci	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
1518c2ecf20Sopenharmony_ci	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
1528c2ecf20Sopenharmony_ci	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
1538c2ecf20Sopenharmony_ci	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
1548c2ecf20Sopenharmony_ci	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
1558c2ecf20Sopenharmony_ci	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
1568c2ecf20Sopenharmony_ci	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
1578c2ecf20Sopenharmony_ci	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
1588c2ecf20Sopenharmony_ci	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
1598c2ecf20Sopenharmony_ci};
1608c2ecf20Sopenharmony_cistatic u32 sizeof_special2 = sizeof(sample_special2);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic u8 sample_special3[] = {
1638c2ecf20Sopenharmony_ci	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
1648c2ecf20Sopenharmony_ci	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
1658c2ecf20Sopenharmony_ci	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
1668c2ecf20Sopenharmony_ci	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
1678c2ecf20Sopenharmony_ci	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
1688c2ecf20Sopenharmony_ci	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
1698c2ecf20Sopenharmony_ci	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
1708c2ecf20Sopenharmony_ci	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
1718c2ecf20Sopenharmony_ci	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
1728c2ecf20Sopenharmony_ci	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_cistatic u32 sizeof_special3 = sizeof(sample_special3);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic u8 sample_silence[] = {
1778c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1788c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1798c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1808c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1818c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1828c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1838c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1848c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1858c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1868c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1878c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1888c2ecf20Sopenharmony_ci	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
1898c2ecf20Sopenharmony_ci};
1908c2ecf20Sopenharmony_cistatic u32 sizeof_silence = sizeof(sample_silence);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistruct tones_samples {
1938c2ecf20Sopenharmony_ci	u32 *len;
1948c2ecf20Sopenharmony_ci	u8 *data;
1958c2ecf20Sopenharmony_ci};
1968c2ecf20Sopenharmony_cistatic struct
1978c2ecf20Sopenharmony_citones_samples samples[] = {
1988c2ecf20Sopenharmony_ci	{&sizeof_german_all, sample_german_all},
1998c2ecf20Sopenharmony_ci	{&sizeof_german_old, sample_german_old},
2008c2ecf20Sopenharmony_ci	{&sizeof_american_dialtone, sample_american_dialtone},
2018c2ecf20Sopenharmony_ci	{&sizeof_american_ringing, sample_american_ringing},
2028c2ecf20Sopenharmony_ci	{&sizeof_american_busy, sample_american_busy},
2038c2ecf20Sopenharmony_ci	{&sizeof_special1, sample_special1},
2048c2ecf20Sopenharmony_ci	{&sizeof_special2, sample_special2},
2058c2ecf20Sopenharmony_ci	{&sizeof_special3, sample_special3},
2068c2ecf20Sopenharmony_ci	{NULL, NULL},
2078c2ecf20Sopenharmony_ci};
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/***********************************
2108c2ecf20Sopenharmony_ci * generate ulaw from alaw samples *
2118c2ecf20Sopenharmony_ci ***********************************/
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_civoid
2148c2ecf20Sopenharmony_cidsp_audio_generate_ulaw_samples(void)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	int i, j;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	i = 0;
2198c2ecf20Sopenharmony_ci	while (samples[i].len) {
2208c2ecf20Sopenharmony_ci		j = 0;
2218c2ecf20Sopenharmony_ci		while (j < (*samples[i].len)) {
2228c2ecf20Sopenharmony_ci			samples[i].data[j] =
2238c2ecf20Sopenharmony_ci				dsp_audio_alaw_to_ulaw[samples[i].data[j]];
2248c2ecf20Sopenharmony_ci			j++;
2258c2ecf20Sopenharmony_ci		}
2268c2ecf20Sopenharmony_ci		i++;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci/****************************
2328c2ecf20Sopenharmony_ci * tone sequence definition *
2338c2ecf20Sopenharmony_ci ****************************/
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic struct pattern {
2368c2ecf20Sopenharmony_ci	int tone;
2378c2ecf20Sopenharmony_ci	u8 *data[10];
2388c2ecf20Sopenharmony_ci	u32 *siz[10];
2398c2ecf20Sopenharmony_ci	u32 seq[10];
2408c2ecf20Sopenharmony_ci} pattern[] = {
2418c2ecf20Sopenharmony_ci	{TONE_GERMAN_DIALTONE,
2428c2ecf20Sopenharmony_ci	 {DATA_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2438c2ecf20Sopenharmony_ci	 {SIZE_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2448c2ecf20Sopenharmony_ci	 {1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDDIALTONE,
2478c2ecf20Sopenharmony_ci	 {DATA_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2488c2ecf20Sopenharmony_ci	 {SIZE_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2498c2ecf20Sopenharmony_ci	 {1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	{TONE_AMERICAN_DIALTONE,
2528c2ecf20Sopenharmony_ci	 {DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2538c2ecf20Sopenharmony_ci	 {SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2548c2ecf20Sopenharmony_ci	 {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	{TONE_GERMAN_DIALPBX,
2578c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL,
2588c2ecf20Sopenharmony_ci	  NULL},
2598c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL,
2608c2ecf20Sopenharmony_ci	  NULL},
2618c2ecf20Sopenharmony_ci	 {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDDIALPBX,
2648c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL,
2658c2ecf20Sopenharmony_ci	  NULL},
2668c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL,
2678c2ecf20Sopenharmony_ci	  NULL},
2688c2ecf20Sopenharmony_ci	 {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	{TONE_AMERICAN_DIALPBX,
2718c2ecf20Sopenharmony_ci	 {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL,
2728c2ecf20Sopenharmony_ci	  NULL},
2738c2ecf20Sopenharmony_ci	 {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL,
2748c2ecf20Sopenharmony_ci	  NULL},
2758c2ecf20Sopenharmony_ci	 {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	{TONE_GERMAN_RINGING,
2788c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2798c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2808c2ecf20Sopenharmony_ci	 {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDRINGING,
2838c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2848c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2858c2ecf20Sopenharmony_ci	 {8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} },
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	{TONE_AMERICAN_RINGING,
2888c2ecf20Sopenharmony_ci	 {DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2898c2ecf20Sopenharmony_ci	 {SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
2908c2ecf20Sopenharmony_ci	 {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	{TONE_GERMAN_RINGPBX,
2938c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
2948c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
2958c2ecf20Sopenharmony_ci	 {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDRINGPBX,
2988c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
2998c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
3008c2ecf20Sopenharmony_ci	 {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	{TONE_AMERICAN_RINGPBX,
3038c2ecf20Sopenharmony_ci	 {DATA_RI, DATA_S, DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
3048c2ecf20Sopenharmony_ci	 {SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
3058c2ecf20Sopenharmony_ci	 {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	{TONE_GERMAN_BUSY,
3088c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3098c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3108c2ecf20Sopenharmony_ci	 {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDBUSY,
3138c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3148c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3158c2ecf20Sopenharmony_ci	 {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	{TONE_AMERICAN_BUSY,
3188c2ecf20Sopenharmony_ci	 {DATA_BU, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3198c2ecf20Sopenharmony_ci	 {SIZE_BU, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3208c2ecf20Sopenharmony_ci	 {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	{TONE_GERMAN_HANGUP,
3238c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3248c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3258c2ecf20Sopenharmony_ci	 {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	{TONE_GERMAN_OLDHANGUP,
3288c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3298c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3308c2ecf20Sopenharmony_ci	 {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	{TONE_AMERICAN_HANGUP,
3338c2ecf20Sopenharmony_ci	 {DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3348c2ecf20Sopenharmony_ci	 {SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3358c2ecf20Sopenharmony_ci	 {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	{TONE_SPECIAL_INFO,
3388c2ecf20Sopenharmony_ci	 {DATA_S1, DATA_S2, DATA_S3, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
3398c2ecf20Sopenharmony_ci	 {SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
3408c2ecf20Sopenharmony_ci	 {2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} },
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	{TONE_GERMAN_GASSENBESETZT,
3438c2ecf20Sopenharmony_ci	 {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3448c2ecf20Sopenharmony_ci	 {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3458c2ecf20Sopenharmony_ci	 {2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0} },
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	{TONE_GERMAN_AUFSCHALTTON,
3488c2ecf20Sopenharmony_ci	 {DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
3498c2ecf20Sopenharmony_ci	 {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
3508c2ecf20Sopenharmony_ci	 {1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} },
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	{0,
3538c2ecf20Sopenharmony_ci	 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3548c2ecf20Sopenharmony_ci	 {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
3558c2ecf20Sopenharmony_ci	 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
3568c2ecf20Sopenharmony_ci};
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci/******************
3598c2ecf20Sopenharmony_ci * copy tone data *
3608c2ecf20Sopenharmony_ci ******************/
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/* an sk_buff is generated from the number of samples needed.
3638c2ecf20Sopenharmony_ci * the count will be changed and may begin from 0 each pattern period.
3648c2ecf20Sopenharmony_ci * the clue is to precalculate the pointers and legths to use only one
3658c2ecf20Sopenharmony_ci * memcpy per function call, or two memcpy if the tone sequence changes.
3668c2ecf20Sopenharmony_ci *
3678c2ecf20Sopenharmony_ci * pattern - the type of the pattern
3688c2ecf20Sopenharmony_ci * count - the sample from the beginning of the pattern (phase)
3698c2ecf20Sopenharmony_ci * len - the number of bytes
3708c2ecf20Sopenharmony_ci *
3718c2ecf20Sopenharmony_ci * return - the sk_buff with the sample
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * if tones has finished (e.g. knocking tone), dsp->tones is turned off
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_civoid dsp_tone_copy(struct dsp *dsp, u8 *data, int len)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	int index, count, start, num;
3788c2ecf20Sopenharmony_ci	struct pattern *pat;
3798c2ecf20Sopenharmony_ci	struct dsp_tone *tone = &dsp->tone;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* if we have no tone, we copy silence */
3828c2ecf20Sopenharmony_ci	if (!tone->tone) {
3838c2ecf20Sopenharmony_ci		memset(data, dsp_silence, len);
3848c2ecf20Sopenharmony_ci		return;
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	/* process pattern */
3888c2ecf20Sopenharmony_ci	pat = (struct pattern *)tone->pattern;
3898c2ecf20Sopenharmony_ci	/* points to the current pattern */
3908c2ecf20Sopenharmony_ci	index = tone->index; /* gives current sequence index */
3918c2ecf20Sopenharmony_ci	count = tone->count; /* gives current sample */
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* copy sample */
3948c2ecf20Sopenharmony_ci	while (len) {
3958c2ecf20Sopenharmony_ci		/* find sample to start with */
3968c2ecf20Sopenharmony_ci		while (42) {
3978c2ecf20Sopenharmony_ci			/* wrap around */
3988c2ecf20Sopenharmony_ci			if (!pat->seq[index]) {
3998c2ecf20Sopenharmony_ci				count = 0;
4008c2ecf20Sopenharmony_ci				index = 0;
4018c2ecf20Sopenharmony_ci			}
4028c2ecf20Sopenharmony_ci			/* check if we are currently playing this tone */
4038c2ecf20Sopenharmony_ci			if (count < pat->seq[index])
4048c2ecf20Sopenharmony_ci				break;
4058c2ecf20Sopenharmony_ci			if (dsp_debug & DEBUG_DSP_TONE)
4068c2ecf20Sopenharmony_ci				printk(KERN_DEBUG "%s: reaching next sequence "
4078c2ecf20Sopenharmony_ci				       "(index=%d)\n", __func__, index);
4088c2ecf20Sopenharmony_ci			count -= pat->seq[index];
4098c2ecf20Sopenharmony_ci			index++;
4108c2ecf20Sopenharmony_ci		}
4118c2ecf20Sopenharmony_ci		/* calculate start and number of samples */
4128c2ecf20Sopenharmony_ci		start = count % (*(pat->siz[index]));
4138c2ecf20Sopenharmony_ci		num = len;
4148c2ecf20Sopenharmony_ci		if (num + count > pat->seq[index])
4158c2ecf20Sopenharmony_ci			num = pat->seq[index] - count;
4168c2ecf20Sopenharmony_ci		if (num + start > (*(pat->siz[index])))
4178c2ecf20Sopenharmony_ci			num = (*(pat->siz[index])) - start;
4188c2ecf20Sopenharmony_ci		/* copy memory */
4198c2ecf20Sopenharmony_ci		memcpy(data, pat->data[index] + start, num);
4208c2ecf20Sopenharmony_ci		/* reduce length */
4218c2ecf20Sopenharmony_ci		data += num;
4228c2ecf20Sopenharmony_ci		count += num;
4238c2ecf20Sopenharmony_ci		len -= num;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci	tone->index = index;
4268c2ecf20Sopenharmony_ci	tone->count = count;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* return sk_buff */
4298c2ecf20Sopenharmony_ci	return;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci/*******************************
4348c2ecf20Sopenharmony_ci * send HW message to hfc card *
4358c2ecf20Sopenharmony_ci *******************************/
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic void
4388c2ecf20Sopenharmony_cidsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	struct sk_buff *nskb;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/* unlocking is not required, because we don't expect a response */
4438c2ecf20Sopenharmony_ci	nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
4448c2ecf20Sopenharmony_ci				(len) ? HFC_SPL_LOOP_ON : HFC_SPL_LOOP_OFF, len, sample,
4458c2ecf20Sopenharmony_ci				GFP_ATOMIC);
4468c2ecf20Sopenharmony_ci	if (nskb) {
4478c2ecf20Sopenharmony_ci		if (dsp->ch.peer) {
4488c2ecf20Sopenharmony_ci			if (dsp->ch.recv(dsp->ch.peer, nskb))
4498c2ecf20Sopenharmony_ci				dev_kfree_skb(nskb);
4508c2ecf20Sopenharmony_ci		} else
4518c2ecf20Sopenharmony_ci			dev_kfree_skb(nskb);
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/*****************
4578c2ecf20Sopenharmony_ci * timer expires *
4588c2ecf20Sopenharmony_ci *****************/
4598c2ecf20Sopenharmony_civoid
4608c2ecf20Sopenharmony_cidsp_tone_timeout(struct timer_list *t)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	struct dsp *dsp = from_timer(dsp, t, tone.tl);
4638c2ecf20Sopenharmony_ci	struct dsp_tone *tone = &dsp->tone;
4648c2ecf20Sopenharmony_ci	struct pattern *pat = (struct pattern *)tone->pattern;
4658c2ecf20Sopenharmony_ci	int index = tone->index;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	if (!tone->tone)
4688c2ecf20Sopenharmony_ci		return;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	index++;
4718c2ecf20Sopenharmony_ci	if (!pat->seq[index])
4728c2ecf20Sopenharmony_ci		index = 0;
4738c2ecf20Sopenharmony_ci	tone->index = index;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* set next tone */
4768c2ecf20Sopenharmony_ci	if (pat->data[index] == DATA_S)
4778c2ecf20Sopenharmony_ci		dsp_tone_hw_message(dsp, NULL, 0);
4788c2ecf20Sopenharmony_ci	else
4798c2ecf20Sopenharmony_ci		dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
4808c2ecf20Sopenharmony_ci	/* set timer */
4818c2ecf20Sopenharmony_ci	tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
4828c2ecf20Sopenharmony_ci	add_timer(&tone->tl);
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci/********************
4878c2ecf20Sopenharmony_ci * set/release tone *
4888c2ecf20Sopenharmony_ci ********************/
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci/*
4918c2ecf20Sopenharmony_ci * tones are relaized by streaming or by special loop commands if supported
4928c2ecf20Sopenharmony_ci * by hardware. when hardware is used, the patterns will be controlled by
4938c2ecf20Sopenharmony_ci * timers.
4948c2ecf20Sopenharmony_ci */
4958c2ecf20Sopenharmony_ciint
4968c2ecf20Sopenharmony_cidsp_tone(struct dsp *dsp, int tone)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct pattern *pat;
4998c2ecf20Sopenharmony_ci	int i;
5008c2ecf20Sopenharmony_ci	struct dsp_tone *tonet = &dsp->tone;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	tonet->software = 0;
5038c2ecf20Sopenharmony_ci	tonet->hardware = 0;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* we turn off the tone */
5068c2ecf20Sopenharmony_ci	if (!tone) {
5078c2ecf20Sopenharmony_ci		if (dsp->features.hfc_loops && timer_pending(&tonet->tl))
5088c2ecf20Sopenharmony_ci			del_timer(&tonet->tl);
5098c2ecf20Sopenharmony_ci		if (dsp->features.hfc_loops)
5108c2ecf20Sopenharmony_ci			dsp_tone_hw_message(dsp, NULL, 0);
5118c2ecf20Sopenharmony_ci		tonet->tone = 0;
5128c2ecf20Sopenharmony_ci		return 0;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	pat = NULL;
5168c2ecf20Sopenharmony_ci	i = 0;
5178c2ecf20Sopenharmony_ci	while (pattern[i].tone) {
5188c2ecf20Sopenharmony_ci		if (pattern[i].tone == tone) {
5198c2ecf20Sopenharmony_ci			pat = &pattern[i];
5208c2ecf20Sopenharmony_ci			break;
5218c2ecf20Sopenharmony_ci		}
5228c2ecf20Sopenharmony_ci		i++;
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci	if (!pat) {
5258c2ecf20Sopenharmony_ci		printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
5268c2ecf20Sopenharmony_ci		return -EINVAL;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci	if (dsp_debug & DEBUG_DSP_TONE)
5298c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n",
5308c2ecf20Sopenharmony_ci		       __func__, tone, 0);
5318c2ecf20Sopenharmony_ci	tonet->tone = tone;
5328c2ecf20Sopenharmony_ci	tonet->pattern = pat;
5338c2ecf20Sopenharmony_ci	tonet->index = 0;
5348c2ecf20Sopenharmony_ci	tonet->count = 0;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	if (dsp->features.hfc_loops) {
5378c2ecf20Sopenharmony_ci		tonet->hardware = 1;
5388c2ecf20Sopenharmony_ci		/* set first tone */
5398c2ecf20Sopenharmony_ci		dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0]));
5408c2ecf20Sopenharmony_ci		/* set timer */
5418c2ecf20Sopenharmony_ci		if (timer_pending(&tonet->tl))
5428c2ecf20Sopenharmony_ci			del_timer(&tonet->tl);
5438c2ecf20Sopenharmony_ci		tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
5448c2ecf20Sopenharmony_ci		add_timer(&tonet->tl);
5458c2ecf20Sopenharmony_ci	} else {
5468c2ecf20Sopenharmony_ci		tonet->software = 1;
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	return 0;
5508c2ecf20Sopenharmony_ci}
551