522 lines
16 KiB
C
Executable File
522 lines
16 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "fft/fft.h"
|
|
#include "cmd_util.h"
|
|
#include "cmd_codec.h"
|
|
#include "cmd_codec_dat.h"
|
|
#include "audio/pcm/audio_pcm.h"
|
|
#include "audio/manager/audio_manager.h"
|
|
|
|
#define CMD_CODEC_PLAY_SND_CARD SND_CARD_0
|
|
#define CMD_CODEC_REC_SND_CARD SND_CARD_1
|
|
|
|
#define FFT_DEBUG_EN 0
|
|
#define RECORD_PCM_BUF_SIZE_48K (768) //max: 48*2*4 * 2 = 768
|
|
#define RECORD_PCM_BUF_SIZE_44K (176400/2) //max: 11025*2*4 * 2 = 176400
|
|
|
|
struct Cmd_Codec_Priv {
|
|
u32 play_sample_rate;
|
|
u8 play_channels;
|
|
u8 play_sample_res;
|
|
|
|
u32 rec_sample_rate;
|
|
u8 rec_channels;
|
|
u8 rec_sample_res;
|
|
} cmd_codec_priv ;
|
|
|
|
FFT_RESULT Cooley_Tukey_FFT(__s32 *data, __u32 fs);
|
|
|
|
/* sample_rate, channels, sample_resolution */
|
|
const unsigned char *play_dat[9][2][2] = {
|
|
{ {play_8k16bit1ch, play_8k32bit1ch}, {play_8k16bit2ch, play_8k32bit2ch} },
|
|
{ {play_11k16bit1ch, play_11k32bit1ch}, {play_11k16bit2ch, play_11k32bit2ch} },
|
|
{ {play_12k16bit1ch, play_12k32bit1ch}, {play_12k16bit2ch, play_12k32bit2ch} },
|
|
{ {play_16k16bit1ch, play_16k32bit1ch}, {play_16k16bit2ch, play_16k32bit2ch} },
|
|
{ {play_22k16bit1ch, play_22k32bit1ch}, {play_22k16bit2ch, play_22k32bit2ch} },
|
|
{ {play_24k16bit1ch, play_24k32bit1ch}, {play_24k16bit2ch, play_24k32bit2ch} },
|
|
{ {play_32k16bit1ch, play_32k32bit1ch}, {play_32k16bit2ch, play_32k32bit2ch} },
|
|
{ {play_44k16bit1ch, play_44k32bit1ch}, {play_44k16bit2ch, play_44k32bit2ch} },
|
|
{ {play_48k16bit1ch, play_48k32bit1ch}, {play_48k16bit2ch, play_48k32bit2ch} },
|
|
};
|
|
|
|
/* sample_rate, channels, sample_resolution */
|
|
const uint16_t play_dat_size[9][2][2] = {
|
|
{ {sizeof(play_8k16bit1ch), sizeof(play_8k32bit1ch)}, {sizeof(play_8k16bit2ch), sizeof(play_8k32bit2ch)} },
|
|
{ {sizeof(play_11k16bit1ch), sizeof(play_11k32bit1ch)}, {sizeof(play_11k16bit2ch), sizeof(play_11k32bit2ch)} },
|
|
{ {sizeof(play_12k16bit1ch), sizeof(play_12k32bit1ch)}, {sizeof(play_12k16bit2ch), sizeof(play_12k32bit2ch)} },
|
|
{ {sizeof(play_16k16bit1ch), sizeof(play_16k32bit1ch)}, {sizeof(play_16k16bit2ch), sizeof(play_16k32bit2ch)} },
|
|
{ {sizeof(play_22k16bit1ch), sizeof(play_22k32bit1ch)}, {sizeof(play_22k16bit2ch), sizeof(play_22k32bit2ch)} },
|
|
{ {sizeof(play_24k16bit1ch), sizeof(play_24k32bit1ch)}, {sizeof(play_24k16bit2ch), sizeof(play_24k32bit2ch)} },
|
|
{ {sizeof(play_32k16bit1ch), sizeof(play_32k32bit1ch)}, {sizeof(play_32k16bit2ch), sizeof(play_32k32bit2ch)} },
|
|
{ {sizeof(play_44k16bit1ch), sizeof(play_44k32bit1ch)}, {sizeof(play_44k16bit2ch), sizeof(play_44k32bit2ch)} },
|
|
{ {sizeof(play_48k16bit1ch), sizeof(play_48k32bit1ch)}, {sizeof(play_48k16bit2ch), sizeof(play_48k32bit2ch)} },
|
|
};
|
|
|
|
|
|
static uint8_t sample_rate_to_num(uint16_t sample_rate)
|
|
{
|
|
switch (sample_rate) {
|
|
case 8000: return 0;
|
|
case 11025: return 1;
|
|
case 12000: return 2;
|
|
case 16000: return 3;
|
|
case 22050: return 4;
|
|
case 24000: return 5;
|
|
case 32000: return 6;
|
|
case 44100: return 7;
|
|
case 48000: return 8;
|
|
default:
|
|
CMD_ERR("invalid sample rate %u\n", sample_rate);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_open_exec(char *cmd)
|
|
{
|
|
int cnt, snd_card_num;
|
|
uint32_t direction, channels, resolution, sampleRate, cmd_param[3];
|
|
|
|
cnt = cmd_sscanf(cmd, "d=%u c=%u r=%u s=%u", &direction, &channels,
|
|
&resolution, &sampleRate);
|
|
if (cnt != 4) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (direction != 0 && direction != 1) {
|
|
CMD_ERR("invalid direction %u\n", direction);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (channels != 1 && channels != 2) {
|
|
CMD_ERR("invalid channels %u\n", channels);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (resolution != 16 && resolution != 24) {
|
|
CMD_ERR("invalid resolution %u\n", resolution);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
switch (sampleRate) {
|
|
case 8000:
|
|
case 16000:
|
|
case 32000:
|
|
|
|
case 12000:
|
|
case 24000:
|
|
case 48000:
|
|
|
|
case 11025:
|
|
case 22050:
|
|
case 44100:
|
|
break;
|
|
|
|
default:
|
|
CMD_ERR("invalid sample rate %u\n", sampleRate);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
struct pcm_config pcm_cfg;
|
|
pcm_cfg.rate = sampleRate;
|
|
pcm_cfg.channels = channels;
|
|
pcm_cfg.format = (resolution == 16) ? PCM_FORMAT_S16_LE : PCM_FORMAT_S24_LE;
|
|
pcm_cfg.period_count = 1;
|
|
|
|
if (direction == PCM_IN) {
|
|
snd_card_num = CMD_CODEC_REC_SND_CARD;
|
|
pcm_cfg.period_size =
|
|
(sampleRate % 1000 ? RECORD_PCM_BUF_SIZE_44K : RECORD_PCM_BUF_SIZE_48K)
|
|
/ (pcm_format_to_bits(pcm_cfg.format) / 8 * channels)
|
|
/ pcm_cfg.period_count;
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_VOLUME_GAIN, AUDIO_IN_DEV_AMIC, VOLUME_GAIN_0dB);
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_ROUTE, AUDIO_IN_DEV_AMIC, AUDIO_DEV_EN);
|
|
if (snd_card_num == SND_CARD_2) {
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_VOLUME_GAIN, AUDIO_IN_DEV_LINEIN, VOLUME_GAIN_0dB);
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_ROUTE, AUDIO_IN_DEV_LINEIN, AUDIO_DEV_EN);
|
|
}
|
|
cmd_codec_priv.rec_sample_rate = sampleRate;
|
|
cmd_codec_priv.rec_channels = channels;
|
|
cmd_codec_priv.rec_sample_res = resolution;
|
|
|
|
cmd_param[0] = 256 << 16 | 256;
|
|
audio_maneger_ioctl(snd_card_num, PLATFORM_IOCTL_SW_CONFIG,
|
|
&cmd_param[0], 1);
|
|
|
|
if (snd_card_num == SND_CARD_2) {
|
|
cmd_param[0] = 0 << 24 | 0x0 << 16 | 0x20 << 8 | 0x1;
|
|
cmd_param[1] = (channels + 1) / 2 * 32;
|
|
cmd_param[2] = 24576000;
|
|
audio_maneger_ioctl(snd_card_num, PLATFORM_IOCTL_HW_CONFIG,
|
|
cmd_param, 3);
|
|
}
|
|
} else {
|
|
snd_card_num = CMD_CODEC_PLAY_SND_CARD;
|
|
pcm_cfg.period_size =
|
|
play_dat_size[sample_rate_to_num(sampleRate)][channels-1][resolution/8-2]
|
|
/ (pcm_format_to_bits(pcm_cfg.format) / 8 * channels)
|
|
/ pcm_cfg.period_count;
|
|
//audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_VOLUME_GAIN, AUDIO_OUT_DEV_SPK, VOLUME_GAIN_0dB);
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_ROUTE, AUDIO_OUT_DEV_SPK, AUDIO_DEV_EN);
|
|
cmd_codec_priv.play_sample_rate = sampleRate;
|
|
cmd_codec_priv.play_channels = channels;
|
|
cmd_codec_priv.play_sample_res = resolution;
|
|
|
|
if (snd_card_num == SND_CARD_0) {
|
|
cmd_param[0] = 256;
|
|
audio_maneger_ioctl(snd_card_num, CODEC_IOCTL_SW_CONFIG, &cmd_param[0], 1);
|
|
} else if (snd_card_num == SND_CARD_2) {
|
|
cmd_param[0] = 256 << 16 | 256;
|
|
audio_maneger_ioctl(snd_card_num, PLATFORM_IOCTL_SW_CONFIG, &cmd_param[0], 1);
|
|
|
|
cmd_param[0] = 0 << 24 | 0x0 << 16 | 0x20 << 8 | 0x1;
|
|
cmd_param[1] = (channels + 1) / 2 * 32;
|
|
cmd_param[2] = 24576000;
|
|
audio_maneger_ioctl(snd_card_num, PLATFORM_IOCTL_HW_CONFIG, cmd_param, 3);
|
|
}
|
|
}
|
|
|
|
if (snd_pcm_open(snd_card_num, (Audio_Stream_Dir)direction, &pcm_cfg)) {
|
|
CMD_ERR("snd pcm open Fail..\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_close_exec(char *cmd)
|
|
{
|
|
int cnt, snd_card_num;
|
|
uint32_t direction;
|
|
|
|
cnt = cmd_sscanf(cmd, "d=%u", &direction);
|
|
if (cnt != 1) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (direction != 0 && direction != 1) {
|
|
CMD_ERR("invalid direction %u\n", direction);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (direction == PCM_IN) {
|
|
snd_card_num = CMD_CODEC_REC_SND_CARD;
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_ROUTE,
|
|
AUDIO_IN_DEV_AMIC, AUDIO_DEV_DIS);
|
|
} else {
|
|
snd_card_num = CMD_CODEC_PLAY_SND_CARD;
|
|
audio_manager_handler(snd_card_num, AUDIO_MANAGER_SET_ROUTE,
|
|
AUDIO_OUT_DEV_SPK, AUDIO_DEV_DIS);
|
|
}
|
|
|
|
if (snd_pcm_close(snd_card_num, (Audio_Stream_Dir)direction)) {
|
|
CMD_ERR("Snd pcm close Fail..\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_pcm_write_exec(char *cmd)
|
|
{
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
uint32_t len = play_dat_size
|
|
[sample_rate_to_num(cmd_codec_priv.play_sample_rate)]
|
|
[cmd_codec_priv.play_channels-1]
|
|
[cmd_codec_priv.play_sample_res/8-2];
|
|
|
|
buf = (uint8_t *)cmd_malloc(len);
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd_malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
cmd_memcpy(buf,
|
|
play_dat[sample_rate_to_num(cmd_codec_priv.play_sample_rate)]
|
|
[cmd_codec_priv.play_channels-1][cmd_codec_priv.play_sample_res/8-2],
|
|
len);
|
|
|
|
size = snd_pcm_write(CMD_CODEC_PLAY_SND_CARD, buf, len);
|
|
if (size != len) {
|
|
CMD_ERR("len = %u, but snd pcm write size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
cmd_write_respond(CMD_STATUS_FAIL, "FAIL");
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
cmd_free(buf);
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_pcm_read_exec(char *cmd)
|
|
{
|
|
int i;
|
|
uint8_t *buf;
|
|
int32_t size;
|
|
uint32_t len = (cmd_codec_priv.rec_sample_rate % 1000)
|
|
? RECORD_PCM_BUF_SIZE_44K : RECORD_PCM_BUF_SIZE_48K;
|
|
|
|
buf = (uint8_t *)cmd_malloc(len);
|
|
if (buf == NULL) {
|
|
CMD_ERR("cmd malloc return NULL.\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_memset(buf, 0, len);
|
|
|
|
size = snd_pcm_read(CMD_CODEC_REC_SND_CARD, buf, len);
|
|
if (size != len) {
|
|
CMD_ERR("len = %u, but snd pcm read size = %d\n", len, size);
|
|
cmd_free(buf);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
cmd_write_respond(CMD_STATUS_OK, "OK");
|
|
|
|
|
|
/********************************** FFT Analyse **********************************/
|
|
#define FFT_POINTS 1024
|
|
|
|
FFT_RESULT fft_result;
|
|
uint16_t *buf_u16 = (uint16_t *)buf;
|
|
uint32_t *buf_u32 = (uint32_t *)buf;
|
|
uint32_t frame_cnt = len
|
|
/ (cmd_codec_priv.rec_sample_res == 16 ? 2 : 4)
|
|
/ cmd_codec_priv.rec_channels;
|
|
s32 *fft_dat = (s32 *)cmd_malloc(FFT_POINTS * 4);
|
|
|
|
#if FFT_DEBUG_EN
|
|
printf("read original data:\n");
|
|
for (i = 0; i < len / 4; i++)
|
|
printf("0x%08x ", buf_u32[i]);
|
|
printf("\n");
|
|
#endif
|
|
|
|
//cmd_memcpy(buf, buf+len/2, len/2);
|
|
|
|
#if FFT_DEBUG_EN
|
|
printf("\n");
|
|
for (i = 0; i < len; i++) {
|
|
printf("%02x ", buf[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
|
|
if (fft_dat == NULL) {
|
|
CMD_ERR("\nMalloc FFT DAT buffer Fail\n\n");
|
|
} else {
|
|
/* AMIC FFT analyse */
|
|
cmd_memset(fft_dat, 0, FFT_POINTS * 4);
|
|
//printf("AMIC FFT buf:\n");
|
|
|
|
if (cmd_codec_priv.rec_sample_res == 16) {
|
|
if (cmd_codec_priv.rec_channels == 1) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u16[i % frame_cnt];
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
} else if (cmd_codec_priv.rec_channels == 2) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u16[2 * (i % frame_cnt)];
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
}
|
|
|
|
} else if (cmd_codec_priv.rec_sample_res == 24) {
|
|
|
|
if (cmd_codec_priv.rec_channels == 1) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u32[i % frame_cnt] >> 16;
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
} else if (cmd_codec_priv.rec_channels == 2) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u32[2 * (i % frame_cnt)] >> 16;
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
fft_result = Cooley_Tukey_FFT(fft_dat, cmd_codec_priv.rec_sample_rate);
|
|
printf("\nAMIC FFT Frequency: %f KHz, SNR: %f dB\n\n",
|
|
fft_result.sig_freq / 1000,
|
|
fft_result.sig_power - fft_result.noise_power);
|
|
|
|
|
|
/* LINEIN FFT analyse */
|
|
if (cmd_codec_priv.rec_channels == 2) {
|
|
cmd_memset(fft_dat, 0, FFT_POINTS * 4);
|
|
//printf("LINEIN FFT buf:\n");
|
|
|
|
if (cmd_codec_priv.rec_sample_res == 16) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u16[2 * (i % frame_cnt) + 1];
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
} else if (cmd_codec_priv.rec_sample_res == 24) {
|
|
for (i = 0; i < FFT_POINTS; i++) {
|
|
fft_dat[i] = buf_u32[2 * (i % frame_cnt) + 1] >> 16;
|
|
//printf("0x%08x\n",fft_dat[i]);
|
|
}
|
|
}
|
|
|
|
fft_result = Cooley_Tukey_FFT(fft_dat, cmd_codec_priv.rec_sample_rate);
|
|
printf("\nLINEIN FFT Frequency: %f KHz, SNR: %f dB\n\n",
|
|
fft_result.sig_freq / 1000,
|
|
fft_result.sig_power - fft_result.noise_power);
|
|
}
|
|
|
|
cmd_free(fft_dat);
|
|
}
|
|
/*********************************************************************************/
|
|
|
|
cmd_free(buf);
|
|
return CMD_STATUS_ACKED;
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_set_route_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t route, enable;
|
|
HAL_Status hal_status;
|
|
Audio_Device audio_device;
|
|
|
|
cnt = cmd_sscanf(cmd, "r=%u e=%u", &route, &enable);
|
|
if (cnt != 2) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
switch (route) {
|
|
case 0:
|
|
audio_device = AUDIO_IN_DEV_AMIC;
|
|
break;
|
|
case 1:
|
|
audio_device = AUDIO_IN_DEV_LINEIN;
|
|
break;
|
|
case 2:
|
|
audio_device = AUDIO_IN_DEV_DMIC;
|
|
break;
|
|
case 3:
|
|
audio_device = AUDIO_OUT_DEV_SPK;
|
|
break;
|
|
default:
|
|
CMD_ERR("invalid route %u\n", route);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (enable != 0 && enable != 1) {
|
|
CMD_ERR("invalid enable %u\n", enable);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
hal_status = audio_manager_handler(CMD_CODEC_PLAY_SND_CARD, AUDIO_MANAGER_SET_ROUTE,
|
|
audio_device, (Audio_Dev_State)enable);
|
|
if (hal_status == HAL_OK) {
|
|
return CMD_STATUS_OK;
|
|
} else {
|
|
CMD_ERR("Codec set route Fail, return: hal_status = %d\n", hal_status);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
}
|
|
|
|
static enum cmd_status cmd_codec_set_gain_exec(char *cmd)
|
|
{
|
|
int cnt;
|
|
uint32_t route, vol_level;
|
|
HAL_Status hal_status;
|
|
Audio_Device audio_device;
|
|
|
|
cnt = cmd_sscanf(cmd, "r=%u g=%u", &route, &vol_level);
|
|
if (cnt != 2) {
|
|
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
switch (route) {
|
|
case 0:
|
|
audio_device = AUDIO_IN_DEV_AMIC;
|
|
break;
|
|
case 1:
|
|
audio_device = AUDIO_IN_DEV_LINEIN;
|
|
break;
|
|
case 3:
|
|
audio_device = AUDIO_OUT_DEV_SPK;
|
|
break;
|
|
case 2:
|
|
default:
|
|
CMD_ERR("invalid route %u\n", route);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
|
|
if (route == 3) {
|
|
if (vol_level < 0 || vol_level > 31) {
|
|
CMD_ERR("invalid vol_level %u\n", vol_level);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
} else {
|
|
if (vol_level < 0 || vol_level > 7) {
|
|
CMD_ERR("invalid vol_level %u\n", vol_level);
|
|
return CMD_STATUS_INVALID_ARG;
|
|
}
|
|
}
|
|
|
|
hal_status = audio_manager_handler(CMD_CODEC_PLAY_SND_CARD, AUDIO_MANAGER_SET_VOLUME_LEVEL,
|
|
audio_device, (Volume_Level)vol_level);
|
|
if (hal_status == HAL_OK) {
|
|
return CMD_STATUS_OK;
|
|
} else {
|
|
CMD_ERR("Codec set vol_level Fail, return: hal_status = %d\n",
|
|
hal_status);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
static const struct cmd_data g_codec_cmds[] = {
|
|
{ "open", cmd_codec_open_exec },
|
|
{ "close", cmd_codec_close_exec },
|
|
{ "pcm_read", cmd_codec_pcm_read_exec },
|
|
{ "pcm_write", cmd_codec_pcm_write_exec },
|
|
{ "set_route", cmd_codec_set_route_exec},
|
|
{ "set_gain", cmd_codec_set_gain_exec},
|
|
};
|
|
|
|
enum cmd_status cmd_codec_exec(char *cmd)
|
|
{
|
|
return cmd_exec(cmd, g_codec_cmds, cmd_nitems(g_codec_cmds));
|
|
}
|
|
|