summaryrefslogtreecommitdiff
path: root/sound/soc/wmt/wmt_swmixer.c
blob: 4d92a81faeef810220035cffea83b6639316bc85 (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
/*++ 
 * linux/sound/soc/wmt/wmt_swmixer.c
 * WonderMedia I2S audio driver for ALSA
 *
 * Copyright c 2010  WonderMedia  Technologies, Inc.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 * WonderMedia Technologies, Inc.
 * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
--*/

 
#include "wmt_swmixer.h"
#include <sound/asound.h>



void wmt_sw_u2s(int fmt, char *buffer, unsigned int chunksize)
{
	unsigned int index;
	if (fmt == SNDRV_PCM_FORMAT_U8) {
		for (index = 0; index < chunksize; ++index)
			*(buffer + index) ^= 0x80;
	}
	
}


void wmt_pcm_fmt_trans(int fmt, int channel, char *src_buf, char *dst_buf, unsigned int chunksize)
{
	unsigned int index = 0;
	float_data_t f_data;
	unsigned short data;

	/* always convert to 2ch, s16le (4 bytes) */
	if ((fmt == SNDRV_PCM_FORMAT_S16_LE) && (channel == 1)) {
		/* transfer from 1ch s16le(2 bytes) to 2ch s16le(4 bytes) */
		for (index = 0; index < (chunksize / 2); ++index) {
			*((unsigned int *)dst_buf + index) = (*((unsigned short *)src_buf + index) << 16 |
						    *((unsigned short *)src_buf + index));
		}	
	}
	else if ((fmt == SNDRV_PCM_FORMAT_U8) && (channel == 1)) {
		/* transfer from 1ch U8(1 bytes) to 2ch s16le(4 bytes) */
		for (index = 0; index < chunksize; ++index) {
			/* padding zero to byte 0 & byte 2 */
			*((unsigned int *)dst_buf + index) = (*((unsigned char *)src_buf + index) << 24 |
						    *((unsigned char *)src_buf + index) << 8);
		}	
	}
	else if ((fmt == SNDRV_PCM_FORMAT_U8) && (channel == 2)) {
		/* transfer from 2ch U8(2 bytes) to 2ch s16le(4 bytes) */
		for (index = 0; index < chunksize; ++index) {
			/* padding zero to byte 0 */
			*((unsigned short *)dst_buf + index) = *((unsigned char *)src_buf + index) << 8;
		}	
	}
	else if ((fmt == SNDRV_PCM_FORMAT_FLOAT) && (channel == 2)) {
		/* transfer from 2ch float(8 bytes) to 2ch s16le(4 bytes) */
		for (index = 0; index < (chunksize / 4); ++index) {
			f_data = *((float_data_t *)src_buf + index);
			
			if (!f_data.sign) {
				data = (f_data.frac + 0x800000) >> (8 - (f_data.exp - 127));
			}
			else {
				data = ~((f_data.frac + 0x800000) >> (8 - (f_data.exp - 127))) + 1;
			}

			*((unsigned short *)dst_buf + index) = data;
		}
	}
	else if ((fmt == SNDRV_PCM_FORMAT_FLOAT) && (channel == 1)) {
		/* transfer from 1ch float(4 bytes) to 2ch s16le(4 bytes) */
		for (index = 0; index < (chunksize / 4); ++index) {
			f_data = *((float_data_t *)src_buf + index);
			
			if (!f_data.sign) {
				data = (unsigned short)((f_data.frac + 0x800000) >> (8 - (f_data.exp - 127)));
			}
			else {
				data = (unsigned short)(~((f_data.frac + 0x800000) >> (8 - (f_data.exp - 127))) + 1);
			}

			*((unsigned int *)dst_buf + index) = (data << 16) | data;
		}
	}	
}