162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci * l1oip_codec.c  generic codec using lookup table
562306a36Sopenharmony_ci *  -> conversion from a-Law to u-Law
662306a36Sopenharmony_ci *  -> conversion from u-Law to a-Law
762306a36Sopenharmony_ci *  -> compression by reducing the number of sample resolution to 4
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * NOTE: It is not compatible with any standard codec like ADPCM.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Author	Andreas Eversberg (jolly@eversberg.eu)
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci  How the codec works:
1962306a36Sopenharmony_ci  --------------------
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci  The volume is increased to increase the dynamic range of the audio signal.
2262306a36Sopenharmony_ci  Each sample is converted to a-LAW with only 16 steps of level resolution.
2362306a36Sopenharmony_ci  A pair of two samples are stored in one byte.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci  The first byte is stored in the upper bits, the second byte is stored in the
2662306a36Sopenharmony_ci  lower bits.
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci  To speed up compression and decompression, two lookup tables are formed:
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci  - 16 bits index for two samples (law encoded) with 8 bit compressed result.
3162306a36Sopenharmony_ci  - 8 bits index for one compressed data with 16 bits decompressed result.
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci  NOTE: The bytes are handled as they are law-encoded.
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci*/
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <linux/vmalloc.h>
3862306a36Sopenharmony_ci#include <linux/mISDNif.h>
3962306a36Sopenharmony_ci#include <linux/in.h>
4062306a36Sopenharmony_ci#include "core.h"
4162306a36Sopenharmony_ci#include "l1oip.h"
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* definitions of codec. don't use calculations, code may run slower. */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic u8 *table_com;
4662306a36Sopenharmony_cistatic u16 *table_dec;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* alaw -> ulaw */
5062306a36Sopenharmony_cistatic u8 alaw_to_ulaw[256] =
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
5362306a36Sopenharmony_ci	0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
5462306a36Sopenharmony_ci	0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
5562306a36Sopenharmony_ci	0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
5662306a36Sopenharmony_ci	0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
5762306a36Sopenharmony_ci	0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
5862306a36Sopenharmony_ci	0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
5962306a36Sopenharmony_ci	0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
6062306a36Sopenharmony_ci	0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
6162306a36Sopenharmony_ci	0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
6262306a36Sopenharmony_ci	0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
6362306a36Sopenharmony_ci	0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
6462306a36Sopenharmony_ci	0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
6562306a36Sopenharmony_ci	0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
6662306a36Sopenharmony_ci	0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
6762306a36Sopenharmony_ci	0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
6862306a36Sopenharmony_ci	0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
6962306a36Sopenharmony_ci	0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
7062306a36Sopenharmony_ci	0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
7162306a36Sopenharmony_ci	0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
7262306a36Sopenharmony_ci	0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
7362306a36Sopenharmony_ci	0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
7462306a36Sopenharmony_ci	0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
7562306a36Sopenharmony_ci	0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
7662306a36Sopenharmony_ci	0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
7762306a36Sopenharmony_ci	0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
7862306a36Sopenharmony_ci	0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
7962306a36Sopenharmony_ci	0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
8062306a36Sopenharmony_ci	0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
8162306a36Sopenharmony_ci	0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
8262306a36Sopenharmony_ci	0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
8362306a36Sopenharmony_ci	0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* ulaw -> alaw */
8762306a36Sopenharmony_cistatic u8 ulaw_to_alaw[256] =
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
9062306a36Sopenharmony_ci	0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
9162306a36Sopenharmony_ci	0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
9262306a36Sopenharmony_ci	0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
9362306a36Sopenharmony_ci	0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
9462306a36Sopenharmony_ci	0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
9562306a36Sopenharmony_ci	0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
9662306a36Sopenharmony_ci	0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
9762306a36Sopenharmony_ci	0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
9862306a36Sopenharmony_ci	0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
9962306a36Sopenharmony_ci	0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
10062306a36Sopenharmony_ci	0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
10162306a36Sopenharmony_ci	0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
10262306a36Sopenharmony_ci	0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
10362306a36Sopenharmony_ci	0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
10462306a36Sopenharmony_ci	0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
10562306a36Sopenharmony_ci	0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
10662306a36Sopenharmony_ci	0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
10762306a36Sopenharmony_ci	0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
10862306a36Sopenharmony_ci	0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
10962306a36Sopenharmony_ci	0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
11062306a36Sopenharmony_ci	0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
11162306a36Sopenharmony_ci	0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
11262306a36Sopenharmony_ci	0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
11362306a36Sopenharmony_ci	0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
11462306a36Sopenharmony_ci	0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
11562306a36Sopenharmony_ci	0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
11662306a36Sopenharmony_ci	0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
11762306a36Sopenharmony_ci	0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
11862306a36Sopenharmony_ci	0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
11962306a36Sopenharmony_ci	0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
12062306a36Sopenharmony_ci	0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
12162306a36Sopenharmony_ci};
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* alaw -> 4bit compression */
12462306a36Sopenharmony_cistatic u8 alaw_to_4bit[256] = {
12562306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
12662306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
12762306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
12862306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
12962306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
13062306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
13162306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
13262306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
13362306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
13462306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
13562306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0d, 0x02,
13662306a36Sopenharmony_ci	0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
13762306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
13862306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
13962306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
14062306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
14162306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
14262306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
14362306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
14462306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
14562306a36Sopenharmony_ci	0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
14662306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x01, 0x0a, 0x05,
14762306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
14862306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x07, 0x0f, 0x00, 0x0b, 0x04,
14962306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
15062306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
15162306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
15262306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
15362306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
15462306a36Sopenharmony_ci	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
15562306a36Sopenharmony_ci	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
15662306a36Sopenharmony_ci	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/* 4bit -> alaw decompression */
16062306a36Sopenharmony_cistatic u8 _4bit_to_alaw[16] = {
16162306a36Sopenharmony_ci	0x5d, 0x51, 0xd9, 0xd7, 0x5f, 0x53, 0xa3, 0x4b,
16262306a36Sopenharmony_ci	0x2a, 0x3a, 0x22, 0x2e, 0x26, 0x56, 0x20, 0x2c,
16362306a36Sopenharmony_ci};
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/* ulaw -> 4bit compression */
16662306a36Sopenharmony_cistatic u8 ulaw_to_4bit[256] = {
16762306a36Sopenharmony_ci	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16862306a36Sopenharmony_ci	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16962306a36Sopenharmony_ci	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17062306a36Sopenharmony_ci	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17162306a36Sopenharmony_ci	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
17262306a36Sopenharmony_ci	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
17362306a36Sopenharmony_ci	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
17462306a36Sopenharmony_ci	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
17562306a36Sopenharmony_ci	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
17662306a36Sopenharmony_ci	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
17762306a36Sopenharmony_ci	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
17862306a36Sopenharmony_ci	0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
17962306a36Sopenharmony_ci	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
18062306a36Sopenharmony_ci	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
18162306a36Sopenharmony_ci	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
18262306a36Sopenharmony_ci	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
18362306a36Sopenharmony_ci	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
18462306a36Sopenharmony_ci	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
18562306a36Sopenharmony_ci	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
18662306a36Sopenharmony_ci	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
18762306a36Sopenharmony_ci	0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
18862306a36Sopenharmony_ci	0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
18962306a36Sopenharmony_ci	0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
19062306a36Sopenharmony_ci	0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
19162306a36Sopenharmony_ci	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
19262306a36Sopenharmony_ci	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b,
19362306a36Sopenharmony_ci	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
19462306a36Sopenharmony_ci	0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a,
19562306a36Sopenharmony_ci	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
19662306a36Sopenharmony_ci	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
19762306a36Sopenharmony_ci	0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
19862306a36Sopenharmony_ci	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci/* 4bit -> ulaw decompression */
20262306a36Sopenharmony_cistatic u8 _4bit_to_ulaw[16] = {
20362306a36Sopenharmony_ci	0x11, 0x21, 0x31, 0x40, 0x4e, 0x5c, 0x68, 0x71,
20462306a36Sopenharmony_ci	0xfe, 0xef, 0xe7, 0xdb, 0xcd, 0xbf, 0xaf, 0x9f,
20562306a36Sopenharmony_ci};
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/*
20962306a36Sopenharmony_ci * Compresses data to the result buffer
21062306a36Sopenharmony_ci * The result size must be at least half of the input buffer.
21162306a36Sopenharmony_ci * The number of samples also must be even!
21262306a36Sopenharmony_ci */
21362306a36Sopenharmony_ciint
21462306a36Sopenharmony_cil1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	int ii, i = 0, o = 0;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (!len)
21962306a36Sopenharmony_ci		return 0;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* send saved byte and first input byte */
22262306a36Sopenharmony_ci	if (*state) {
22362306a36Sopenharmony_ci		*result++ = table_com[(((*state) << 8) & 0xff00) | (*data++)];
22462306a36Sopenharmony_ci		len--;
22562306a36Sopenharmony_ci		o++;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	ii = len >> 1;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	while (i < ii) {
23162306a36Sopenharmony_ci		*result++ = table_com[(data[0]<<8) | (data[1])];
23262306a36Sopenharmony_ci		data += 2;
23362306a36Sopenharmony_ci		i++;
23462306a36Sopenharmony_ci		o++;
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* if len has an odd number, we save byte for next call */
23862306a36Sopenharmony_ci	if (len & 1)
23962306a36Sopenharmony_ci		*state = 0x100 + *data;
24062306a36Sopenharmony_ci	else
24162306a36Sopenharmony_ci		*state = 0;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return o;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/* Decompress data to the result buffer
24762306a36Sopenharmony_ci * The result size must be the number of sample in packet. (2 * input data)
24862306a36Sopenharmony_ci * The number of samples in the result are even!
24962306a36Sopenharmony_ci */
25062306a36Sopenharmony_ciint
25162306a36Sopenharmony_cil1oip_4bit_to_law(u8 *data, int len, u8 *result)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	int i = 0;
25462306a36Sopenharmony_ci	u16 r;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	while (i < len) {
25762306a36Sopenharmony_ci		r = table_dec[*data++];
25862306a36Sopenharmony_ci		*result++ = r >> 8;
25962306a36Sopenharmony_ci		*result++ = r;
26062306a36Sopenharmony_ci		i++;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	return len << 1;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/*
26862306a36Sopenharmony_ci * law conversion
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_ciint
27162306a36Sopenharmony_cil1oip_alaw_to_ulaw(u8 *data, int len, u8 *result)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	int i = 0;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	while (i < len) {
27662306a36Sopenharmony_ci		*result++ = alaw_to_ulaw[*data++];
27762306a36Sopenharmony_ci		i++;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	return len;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ciint
28462306a36Sopenharmony_cil1oip_ulaw_to_alaw(u8 *data, int len, u8 *result)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	int i = 0;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	while (i < len) {
28962306a36Sopenharmony_ci		*result++ = ulaw_to_alaw[*data++];
29062306a36Sopenharmony_ci		i++;
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	return len;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci/*
29862306a36Sopenharmony_ci * generate/free compression and decompression table
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_civoid
30162306a36Sopenharmony_cil1oip_4bit_free(void)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	vfree(table_dec);
30462306a36Sopenharmony_ci	vfree(table_com);
30562306a36Sopenharmony_ci	table_com = NULL;
30662306a36Sopenharmony_ci	table_dec = NULL;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ciint
31062306a36Sopenharmony_cil1oip_4bit_alloc(int ulaw)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	int i1, i2, c, sample;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/* in case, it is called again */
31562306a36Sopenharmony_ci	if (table_dec)
31662306a36Sopenharmony_ci		return 0;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* alloc conversion tables */
31962306a36Sopenharmony_ci	table_com = vzalloc(65536);
32062306a36Sopenharmony_ci	table_dec = vzalloc(512);
32162306a36Sopenharmony_ci	if (!table_com || !table_dec) {
32262306a36Sopenharmony_ci		l1oip_4bit_free();
32362306a36Sopenharmony_ci		return -ENOMEM;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci	/* generate compression table */
32662306a36Sopenharmony_ci	i1 = 0;
32762306a36Sopenharmony_ci	while (i1 < 256) {
32862306a36Sopenharmony_ci		if (ulaw)
32962306a36Sopenharmony_ci			c = ulaw_to_4bit[i1];
33062306a36Sopenharmony_ci		else
33162306a36Sopenharmony_ci			c = alaw_to_4bit[i1];
33262306a36Sopenharmony_ci		i2 = 0;
33362306a36Sopenharmony_ci		while (i2 < 256) {
33462306a36Sopenharmony_ci			table_com[(i1 << 8) | i2] |= (c << 4);
33562306a36Sopenharmony_ci			table_com[(i2 << 8) | i1] |= c;
33662306a36Sopenharmony_ci			i2++;
33762306a36Sopenharmony_ci		}
33862306a36Sopenharmony_ci		i1++;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/* generate decompression table */
34262306a36Sopenharmony_ci	i1 = 0;
34362306a36Sopenharmony_ci	while (i1 < 16) {
34462306a36Sopenharmony_ci		if (ulaw)
34562306a36Sopenharmony_ci			sample = _4bit_to_ulaw[i1];
34662306a36Sopenharmony_ci		else
34762306a36Sopenharmony_ci			sample = _4bit_to_alaw[i1];
34862306a36Sopenharmony_ci		i2 = 0;
34962306a36Sopenharmony_ci		while (i2 < 16) {
35062306a36Sopenharmony_ci			table_dec[(i1 << 4) | i2] |= (sample << 8);
35162306a36Sopenharmony_ci			table_dec[(i2 << 4) | i1] |= sample;
35262306a36Sopenharmony_ci			i2++;
35362306a36Sopenharmony_ci		}
35462306a36Sopenharmony_ci		i1++;
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	return 0;
35862306a36Sopenharmony_ci}
359