Merge branch 'master' of ssh://g.hz.netease.com:22222/IoT/PV2/SmartAudioPV2

This commit is contained in:
HuangXin 2018-08-27 10:15:13 +08:00
commit ad4d7723a0
26 changed files with 3304 additions and 192 deletions

View File

@ -836,8 +836,7 @@ dtb-$(CONFIG_ARCH_SUN8IW6P1) += \
sun8iw6p1-soc.dtb sun8iw6p1-soc.dtb
dtb-$(CONFIG_ARCH_SUN8IW15P1) += \ dtb-$(CONFIG_ARCH_SUN8IW15P1) += \
sun8iw15p1-soc.dtb \ sun8iw15p1-soc.dtb \
sun8iw15p1-mandolin-perf1.dtb\ sun8iw15p1-mandolin-perf1.dtb
sun8iw15p1-mandolin-pv1.dtb
dtb-$(CONFIG_ARCH_TANGO) += \ dtb-$(CONFIG_ARCH_TANGO) += \
tango4-vantage-1172.dtb tango4-vantage-1172.dtb
dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \

View File

@ -10,20 +10,9 @@
/{ /{
soc@03000000 { soc@03000000 {
twi0: twi@0x05002000{
status = "disabled";
ad82584f@31 {
compatible = "ESMT, ad82584f";
reg = <0x31>;
reset_pin = <&r_pio PL 11 1 1 1 1>;
amp_en = <&r_pio PL 3 1 1 1 1>;
};
};
snddaudio0:sound@1{ snddaudio0:sound@1{
sunxi,snddaudio-codec = "ad82584f.0-0031"; sunxi,snddaudio-codec = "netease1.mic.codec";
sunxi,snddaudio-codec-dai = "ad82584f"; sunxi,snddaudio-codec-dai = "netease1.mic.codecdai";
}; };
wlan:wlan { wlan:wlan {

View File

@ -10,20 +10,9 @@
/{ /{
soc@03000000 { soc@03000000 {
twi0: twi@0x05002000{
status = "disabled";
ad82584f@31 {
compatible = "ESMT, ad82584f";
reg = <0x31>;
reset_pin = <&r_pio PL 11 1 1 1 1>;
amp_en = <&r_pio PL 3 1 1 1 1>;
};
};
snddaudio0:sound@1{ snddaudio0:sound@1{
sunxi,snddaudio-codec = "ad82584f.0-0031"; sunxi,snddaudio-codec = "netease1.mic.codec";
sunxi,snddaudio-codec-dai = "ad82584f"; sunxi,snddaudio-codec-dai = "netease1.mic.codecdai";
}; };
wlan:wlan { wlan:wlan {

View File

@ -1 +1 @@
obj-$(CONFIG_XUNFEI_CPLD) += cpld/i2c_operator.o cpld/fpga_loader.o cpld/fpga_config.o cpld/cx20810.o cpld/netease_config.o obj-$(CONFIG_XUNFEI_CPLD) += cpld/fpga_loader.o cpld/i2c_operator.o cpld/cx20810.o cpld/netease_config.o

View File

@ -1089,6 +1089,10 @@ config SND_SOC_TPA6130A2
tristate "Texas Instruments TPA6130A2 headphone amplifier" tristate "Texas Instruments TPA6130A2 headphone amplifier"
depends on I2C depends on I2C
config SND_SOC_ES7243
tristate "SND_SOC_ES7243"
depends on I2C
endmenu endmenu
# Wolfgang add ACX00 # Wolfgang add ACX00

View File

@ -446,3 +446,4 @@ obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
# Wolfgang add ACX00 # Wolfgang add ACX00
obj-$(CONFIG_SND_SOC_ACX00) += snd-soc-acx00.o obj-$(CONFIG_SND_SOC_ACX00) += snd-soc-acx00.o
obj-$(CONFIG_SND_SOC_AD82584F) += snd-soc-ad82584f.o obj-$(CONFIG_SND_SOC_AD82584F) += snd-soc-ad82584f.o
obj-$(CONFIG_SND_SOC_ES7243) += es7243.o

View File

@ -0,0 +1,972 @@
/*
* ALSA SoC ES7243 adc driver
*
* Author: David Yang, <yangxiaohua@everest-semi.com>
* or
* <info@everest-semi.com>
* Copyright: (C) 2017 Everest Semiconductor Co Ltd.,
*
* Based on sound/soc/codecs/wm8731.c by Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Notes:
* ES7243 is a stereo ADC of Everest
*
*/
#define DEBUG
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "es7243.h"
#define ES7243_TDM_ENABLE 0
#define ES7243_CHANNELS_MAX 2
#define ES7243_I2C_BUS_NUM 0
#define ES7243_CODEC_RW_TEST_EN 0
#define ES7243_IDLE_RESET_EN 1 // reset ES7243 when in idle time
#define ES7243_MATCH_DTS_EN \
0 // ES7243 match method select: 0: i2c_detect, 1:of_device_id
struct i2c_client *i2c_clt[(ES7243_CHANNELS_MAX) / 2];
/* codec private data */
struct es7243_priv {
struct regmap *regmap;
struct i2c_client *i2c;
unsigned int dmic_amic;
unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
unsigned int tdm;
struct delayed_work pcm_pop_work;
struct delayed_work pcm_pop_work1;
};
struct snd_soc_codec *tron_codec[4];
int es7243_init_reg = 0;
static int es7243_codec_num = 0;
static const struct regmap_config es7243_regmap_config = {
.reg_bits = 8, // Number of bits in a register address
.val_bits = 8, // Number of bits in a register value
};
/*
* ES7243 register cache
*/
static const u8 es7243_reg[] = {
0x00, 0x00, 0x10, 0x04, /* 0 */
0x02, 0x13, 0x00, 0x3f, /* 4 */
0x11, 0x00, 0xc0, 0xc0, /* 8 */
0x12, 0xa0, 0x40, /* 12 */
};
static const struct reg_default es7243_reg_defaults[] = {
{0x00, 0x00}, {0x01, 0x00}, {0x02, 0x10}, {0x03, 0x04}, /* 0 */
{0x04, 0x02}, {0x05, 0x13}, {0x06, 0x00}, {0x07, 0x3f}, /* 4 */
{0x08, 0x11}, {0x09, 0x00}, {0x0a, 0xc0}, {0x0b, 0xc0}, /* 8 */
{0x0c, 0x12}, {0x0d, 0xa0}, {0x0e, 0x40}, /* 12 */
};
static int es7243_read(u8 reg, u8 *rt_value, struct i2c_client *client) {
int ret;
u8 read_cmd[3] = {0};
u8 cmd_len = 0;
read_cmd[0] = reg;
cmd_len = 1;
if (client->adapter == NULL)
pr_err("es7243_read client->adapter==NULL\n");
ret = i2c_master_send(client, read_cmd, cmd_len);
if (ret != cmd_len) {
pr_err("es7243_read error1\n");
return -1;
}
ret = i2c_master_recv(client, rt_value, 1);
if (ret != 1) {
pr_err("es7243_read error2, ret = %d.\n", ret);
return -1;
}
return 0;
}
static int es7243_write(u8 reg, unsigned char value,
struct i2c_client *client) {
int ret = 0;
u8 write_cmd[2] = {0};
write_cmd[0] = reg;
write_cmd[1] = value;
ret = i2c_master_send(client, write_cmd, 2);
if (ret != 2) {
pr_err("es7243_write error->[REG-0x%02x,val-0x%02x]\n", reg, value);
return -1;
}
return 0;
}
static int es7243_update_bits(u8 reg, u8 mask, u8 value,
struct i2c_client *client) {
u8 val_old, val_new;
es7243_read(reg, &val_old, client);
val_new = (val_old & ~mask) | (value & mask);
if (val_new != val_old) {
es7243_write(reg, val_new, client);
}
return 0;
}
#if 0
static int es7243_multi_chips_read(u8 reg, unsigned char *rt_value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_read(reg, rt_value++, i2c_clt[i]);
}
return 0;
}
static int es7243_multi_chips_write(u8 reg, unsigned char value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_write(reg, value, i2c_clt[i]);
}
return 0;
}
#endif
#if 0
static int es7243_multi_chips_update_bits(u8 reg, u8 mask, u8 value)
{
u8 i;
for(i=0; i<(ES7243_CHANNELS_MAX)/2; i++){
es7243_update_bits(reg, mask, value, i2c_clt[i]);
}
return 0;
}
#endif
struct _coeff_div {
u32 mclk; // mclk frequency
u32 sr_rate; // sample rate
u8 speedmode; // speed mode,0=single,1=double,2=quad
u8 adc_clk_div; // adcclk and dacclk divider
u8 lrckdiv; // adclrck divider and daclrck divider
u8 bclkdiv; // sclk divider
u8 osr; // adc osr
};
/* codec hifi mclk clock divider coefficients */
static const struct _coeff_div coeff_div[] = {
/* 12.288MHZ */
{12288000, 8000, 0, 0x0c, 0x60, 24, 32},
{12288000, 12000, 0, 0x08, 0x40, 16, 32},
{12288000, 16000, 0, 0x06, 0x30, 12, 32},
{12288000, 24000, 0, 0x04, 0x20, 8, 32},
{12288000, 32000, 0, 0x03, 0x18, 6, 32},
{12288000, 48000, 0, 0x02, 0x10, 4, 32},
{12288000, 64000, 1, 0x03, 0x0c, 3, 32},
{12288000, 96000, 1, 0x02, 0x08, 2, 32},
/* 11.2896MHZ */
{11289600, 11025, 0, 0x08, 0x40, 16, 32},
{11289600, 22050, 0, 0x04, 0x20, 8, 32},
{11289600, 44100, 0, 0x02, 0x10, 4, 32},
{11289600, 88200, 1, 0x02, 0x08, 2, 32},
/* 12.000MHZ */
{12000000, 8000, 0, 0x0c, 0xbc, 30, 31},
{12000000, 11025, 0, 0x08, 0x44, 17, 34},
{12000000, 12000, 0, 0x08, 0xaa, 20, 31},
{12000000, 16000, 0, 0x06, 0x9e, 15, 31},
{12000000, 22050, 0, 0x04, 0x22, 8, 34},
{12000000, 24000, 0, 0x04, 0x94, 10, 31},
{12000000, 32000, 0, 0x03, 0x8a, 5, 31},
{12000000, 44100, 0, 0x02, 0x11, 4, 34},
{12000000, 48000, 0, 0x02, 0x85, 5, 31},
{12000000, 96000, 1, 0x02, 0x85, 1, 31},
};
static inline int get_coeff(int mclk, int rate) {
int i;
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
if (coeff_div[i].sr_rate == rate && coeff_div[i].mclk == mclk)
return i;
}
return -EINVAL;
}
/* The set of rates we can generate from the above for each SYSCLK */
static unsigned int rates_12288[] = {
8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
};
static struct snd_pcm_hw_constraint_list constraints_12288 = {
.count = ARRAY_SIZE(rates_12288),
.list = rates_12288,
};
static unsigned int rates_112896[] = {
8000,
11025,
22050,
44100,
};
static struct snd_pcm_hw_constraint_list constraints_112896 = {
.count = ARRAY_SIZE(rates_112896),
.list = rates_112896,
};
static unsigned int rates_12[] = {
8000, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 48000, 88235, 96000,
};
static struct snd_pcm_hw_constraint_list constraints_12 = {
.count = ARRAY_SIZE(rates_12),
.list = rates_12,
};
/*
* Note that this should be called from init rather than from hw_params.
*/
static int es7243_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
unsigned int freq, int dir) {
struct snd_soc_codec *codec = codec_dai->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
printk("es7243_set_dai_sysclk: %d\n", freq);
switch (freq) {
case 11289600:
case 22579200:
es7243->sysclk_constraints = &constraints_112896;
es7243->sysclk = freq;
return 0;
case 12288000:
case 24576000:
es7243->sysclk_constraints = &constraints_12288;
es7243->sysclk = freq;
return 0;
case 12000000:
case 24000000:
es7243->sysclk_constraints = &constraints_12;
es7243->sysclk = freq;
return 0;
}
return -EINVAL;
}
static int es7243_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) {
// struct snd_soc_codec *codec = codec_dai->codec;
u8 iface = 0;
u8 adciface = 0;
u8 i;
printk("es7243_set_dai_fmt:%d\n", fmt);
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_read(ES7243_SDPFMT_REG01, &adciface, i2c_clt[i]);
es7243_read(ES7243_MODECFG_REG00, &iface, i2c_clt[i]);
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: // MASTER MODE
iface |= 0x02;
break;
case SND_SOC_DAIFMT_CBS_CFS: // SLAVE MODE
iface &= 0xfd;
break;
default:
return -EINVAL;
}
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
adciface &= 0xFC;
break;
case SND_SOC_DAIFMT_RIGHT_J:
return -EINVAL;
case SND_SOC_DAIFMT_LEFT_J:
adciface &= 0xFC;
adciface |= 0x01;
break;
case SND_SOC_DAIFMT_DSP_A:
adciface &= 0xDC;
adciface |= 0x03;
break;
case SND_SOC_DAIFMT_DSP_B:
adciface &= 0xDC;
adciface |= 0x23;
break;
default:
return -EINVAL;
}
/* clock inversion */
adciface &= 0xbF;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
adciface &= 0xbF;
break;
case SND_SOC_DAIFMT_IB_IF:
adciface |= 0x60;
break;
case SND_SOC_DAIFMT_IB_NF:
adciface |= 0x40;
break;
case SND_SOC_DAIFMT_NB_IF:
adciface |= 0x20;
break;
default:
return -EINVAL;
}
// es7243_update_bits(ES7243_MODECFG_REG00, 0x02, iface, i2c_clt[i]);
// es7243_update_bits(ES7243_SDPFMT_REG01, 0x03, adciface, i2c_clt[i]);
}
return 0;
}
static void es7243_init_codec(struct snd_soc_codec *codec, u8 i) {
printk("Init es7243\n");
es7243_write(ES7243_MODECFG_REG00, 0x41,
i2c_clt[i]); // enter into hardware mode, mclk / 3
es7243_write(ES7243_STATECTL_REG06, 0x18, i2c_clt[i]); // soft reset codec
// es7243_write(ES7243_SDPFMT_REG01, 0xd3, i2c_clt[i]); //dsp for tdm mode,
// DSP-A, 32BIT, bclk invert
es7243_write(ES7243_SDPFMT_REG01, 0x0d, i2c_clt[i]); // lj-16bit
es7243_write(ES7243_LRCDIV_REG02, 0x10, i2c_clt[i]);
es7243_write(ES7243_BCKDIV_REG03, 0x04, i2c_clt[i]);
es7243_write(ES7243_CLKDIV_REG04, 0x02, i2c_clt[i]);
es7243_write(ES7243_MUTECTL_REG05, 0x1a, i2c_clt[i]);
es7243_write(ES7243_ANACTL1_REG08, 0x43,
i2c_clt[i]); // enable microphone input and pga gain for 27db
es7243_write(ES7243_ANACTL2_REG09, 0x3F, i2c_clt[i]);
es7243_write(ES7243_STATECTL_REG06, 0x00, i2c_clt[i]);
es7243_write(ES7243_MUTECTL_REG05, 0x12, i2c_clt[i]);
// if(i == 3) {
// es7243_write(ES7243_ANACTL1_REG08, 0x11, i2c_clt[i]);
//}
// else {
es7243_write(ES7243_ANACTL1_REG08, 0x43,
i2c_clt[i]); // enable microphone input and pga gain for 27db
//}
es7243_write(ES7243_STATECTL_REG06, 0x00, i2c_clt[i]);
}
static void es7243_unmute(struct snd_soc_codec *codec, u8 i) {
es7243_write(ES7243_MUTECTL_REG05, 0x13, i2c_clt[i]);
}
static void pcm_pop_work1_events(struct work_struct *work) {
int i;
printk("es8316--------pcm_pop_work_events\n");
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_unmute(tron_codec[(ES7243_CHANNELS_MAX / 2 - 1) - i],
(ES7243_CHANNELS_MAX / 2 - 1 - i));
}
es7243_init_reg = 1;
}
static void pcm_pop_work_events(struct work_struct *work) {
int i;
printk("es8316--------pcm_pop_work_events\n");
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_init_codec(tron_codec[i], i);
}
es7243_init_reg = 1;
}
static int es7243_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) {
struct snd_soc_codec *codec = dai->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
return 0;
/* The set of sample rates that can be supported depends on the
* MCLK supplied to the CODEC - enforce this.
*/
if (!es7243->sysclk) {
dev_err(codec->dev, "No MCLK configured, call set_sysclk() on init\n");
return -EINVAL;
}
snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
es7243->sysclk_constraints);
return 0;
}
static int es7243_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
u8 i, val;
if (es7243_init_reg == 0 || 1) {
printk(
"==================>>>>>>>>es8316_pcm_startup es8316_init_reg=0\n");
// schedule_delayed_work(&es7243->pcm_pop_work, msecs_to_jiffies(100));
schedule_delayed_work(&es7243->pcm_pop_work, 0);
schedule_delayed_work(&es7243->pcm_pop_work1, msecs_to_jiffies(700));
}
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
es7243_read(ES7243_MODECFG_REG00, &val,
i2c_clt[i]); // enter into hardware mode
printk("%d -- Reg 00 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_STATECTL_REG06, &val, i2c_clt[i]); // soft reset
// codec
printk("%d -- Reg 06 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_SDPFMT_REG01, &val,
i2c_clt[i]); // dsp for tdm mode, DSP-A, 16BIT
printk("%d -- Reg 01 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_LRCDIV_REG02, &val, i2c_clt[i]);
printk("%d -- Reg 02 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_BCKDIV_REG03, &val, i2c_clt[i]);
printk("%d -- Reg 03 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_CLKDIV_REG04, &val, i2c_clt[i]);
printk("%d -- Reg 04 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_MUTECTL_REG05, &val, i2c_clt[i]);
printk("%d -- Reg 05 ----> 0x%x!\n", __LINE__, val);
es7243_read(
ES7243_ANACTL1_REG08, &val,
i2c_clt[i]); // enable microphone input and pga gain for 27db
printk("%d -- Reg 08 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_ANACTL2_REG09, &val, i2c_clt[i]);
printk("%d -- Reg 09 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_STATECTL_REG06, &val, i2c_clt[i]);
printk("%d -- Reg 06 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_ANACTL0_REG07, &val,
i2c_clt[i]); // power up adc and analog input
printk("%d -- Reg 07 ----> 0x%x!\n", __LINE__, val);
es7243_read(ES7243_MUTECTL_REG05, &val, i2c_clt[i]);
printk("%d -- Reg 05 ----> 0x%x!\n", __LINE__, val);
}
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
/* bit size */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x0c, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S20_3LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x04, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S24_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x00, i2c_clt[i]);
break;
case SNDRV_PCM_FORMAT_S32_LE:
es7243_update_bits(ES7243_SDPFMT_REG01, 0x1c, 0x10, i2c_clt[i]);
break;
}
}
return 0;
}
static int es7243_mute(struct snd_soc_dai *dai, int mute) {
struct snd_soc_codec *codec = dai->codec;
u8 i;
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
dev_dbg(codec->dev, "%s %d\n", __func__, mute);
if (mute) {
// es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08,
// i2c_clt[i]);
} else {
// es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x00,
// i2c_clt[i]);
}
}
return 0;
}
static int es7243_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) {
u8 i;
for (i = 0; i < (ES7243_CHANNELS_MAX) / 2; i++) {
switch (level) {
case SND_SOC_BIAS_ON:
dev_dbg(codec->dev, "%s on\n", __func__);
break;
case SND_SOC_BIAS_PREPARE:
dev_dbg(codec->dev, "%s prepare\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x00, i2c_clt[i]);
msleep(50);
break;
case SND_SOC_BIAS_STANDBY:
dev_dbg(codec->dev, "%s standby\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08, i2c_clt[i]);
es7243_update_bits(ES7243_STATECTL_REG06, 0x40, 0x00, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_ANACTL0_REG07, 0x0f, 0x00, i2c_clt[i]);
break;
case SND_SOC_BIAS_OFF:
dev_dbg(codec->dev, "%s off\n", __func__);
es7243_update_bits(ES7243_MUTECTL_REG05, 0x08, 0x08, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_ANACTL0_REG07, 0x0f, 0x0f, i2c_clt[i]);
msleep(50);
es7243_update_bits(ES7243_STATECTL_REG06, 0x40, 0x40, i2c_clt[i]);
break;
}
}
// codec->dapm.bias_level = level;
return 0;
}
#define es7243_RATES SNDRV_PCM_RATE_8000_96000
#define es7243_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
static struct snd_soc_dai_ops es7243_ops = {
.startup = es7243_pcm_startup,
.hw_params = es7243_pcm_hw_params,
.set_fmt = es7243_set_dai_fmt,
.set_sysclk = es7243_set_dai_sysclk,
.digital_mute = es7243_mute,
};
static struct snd_soc_dai_driver es7243_dai0 = {
.name = "es7243",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai1 = {
.name = "ES7243 HiFi 1",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai2 = {
.name = "ES7243 HiFi 2",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver es7243_dai3 = {
.name = "ES7243 HiFi 3",
.capture =
{
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = es7243_RATES,
.formats = es7243_FORMATS,
},
.ops = &es7243_ops,
.symmetric_rates = 1,
};
static struct snd_soc_dai_driver *es7243_dai[] = {
#if ES7243_CHANNELS_MAX > 0
&es7243_dai0,
#endif
#if ES7243_CHANNELS_MAX > 2
&es7243_dai1,
#endif
#if ES7243_CHANNELS_MAX > 4
&es7243_dai2,
#endif
#if ES7243_CHANNELS_MAX > 6
&es7243_dai3,
#endif
};
static int es7243_suspend(struct snd_soc_codec *codec) {
es7243_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int es7243_resume(struct snd_soc_codec *codec) {
snd_soc_cache_sync(codec);
es7243_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static int es7243_probe(struct snd_soc_codec *codec) {
struct es7243_priv *es7243 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
#if !ES7243_CODEC_RW_TEST_EN
// ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);//8,8
#else
codec->control_data =
devm_regmap_init_i2c(es7243->i2c, &es7243_regmap_config);
ret = PTR_RET(codec->control_data);
#endif
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
printk("begin->>>>>>>>>>%s!\n", __func__);
tron_codec[es7243_codec_num++] = codec;
INIT_DELAYED_WORK(&es7243->pcm_pop_work, pcm_pop_work_events);
INIT_DELAYED_WORK(&es7243->pcm_pop_work1, pcm_pop_work1_events);
return 0;
}
static int es7243_remove(struct snd_soc_codec *codec) {
es7243_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_es7243 = {
.probe = es7243_probe,
.remove = es7243_remove,
.suspend = es7243_suspend,
.resume = es7243_resume,
.set_bias_level = es7243_set_bias_level,
.idle_bias_off = true,
.reg_word_size = sizeof(u8),
#if ES7243_CODEC_RW_TEST_EN
.read = es7243_codec_read,
.write = es7243_codec_write,
#endif
};
static ssize_t es7243_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) {
int val = 0, flag = 0;
u8 i = 0, reg, num, value_w, value_r;
struct es7243_priv *es7243 = dev_get_drvdata(dev);
val = simple_strtol(buf, NULL, 16);
flag = (val >> 16) & 0xFF;
if (flag) {
reg = (val >> 8) & 0xFF;
value_w = val & 0xFF;
printk("\nWrite: start REG:0x%02x,val:0x%02x,count:0x%02x\n", reg,
value_w, flag);
while (flag--) {
es7243_write(reg, value_w, es7243->i2c);
printk("Write 0x%02x to REG:0x%02x\n", value_w, reg);
reg++;
}
} else {
reg = (val >> 8) & 0xFF;
num = val & 0xff;
printk("\nRead: start REG:0x%02x,count:0x%02x\n", reg, num);
do {
value_r = 0;
es7243_read(reg, &value_r, es7243->i2c);
printk("REG[0x%02x]: 0x%02x; ", reg, value_r);
reg++;
i++;
if ((i == num) || (i % 4 == 0))
printk("\n");
} while (i < num);
}
return count;
}
static ssize_t es7243_show(struct device *dev, struct device_attribute *attr,
char *buf) {
printk("echo flag|reg|val > es7243\n");
printk("eg read star addres=0x06,count 0x10:echo 0610 >es7243\n");
printk("eg write star addres=0x90,value=0x3c,count=4:echo 4903c >es7243\n");
// printk("eg write value:0xfe to address:0x06 :echo 106fe > es7243\n");
return 0;
}
static DEVICE_ATTR(es7243, 0644, es7243_show, es7243_store);
static struct attribute *es7243_debug_attrs[] = {
&dev_attr_es7243.attr,
NULL,
};
static struct attribute_group es7243_debug_attr_group = {
.name = "es7243_debug",
.attrs = es7243_debug_attrs,
};
//#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
*/
static int es7243_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id) {
struct es7243_priv *es7243;
int ret;
// struct device_node *np = i2c->dev.of_node;
printk("es7243_i2c_probe begin->>>>>>>>>>%s!\n", __func__);
es7243 = devm_kzalloc(&i2c->dev, sizeof(struct es7243_priv), GFP_KERNEL);
if (es7243 == NULL)
return -ENOMEM;
es7243->i2c = i2c;
es7243->tdm = ES7243_TDM_ENABLE; // to initialize tdm mode
dev_set_drvdata(&i2c->dev, es7243);
// i2c_set_clientdata(i2c, es7243);
// es7243->regmap = devm_regmap_init_i2c(i2c, &es7243_regmap);
// if (IS_ERR(es7243->regmap)) {
// ret = PTR_ERR(es7243->regmap);
// dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
// ret);
// return ret;
// }
printk("%s, drivedata:%d\n", __func__, i2c_id->driver_data);
if (i2c_id->driver_data < (ES7243_CHANNELS_MAX) / 2) {
i2c_clt[i2c_id->driver_data] = i2c;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_es7243,
es7243_dai[i2c_id->driver_data], 1);
if (ret < 0) {
kfree(es7243);
return ret;
}
printk("begin to registe codec:%s, ret:%d\n",
es7243_dai[i2c_id->driver_data]->name, ret);
}
ret = sysfs_create_group(&i2c->dev.kobj, &es7243_debug_attr_group);
if (ret) {
pr_err("failed to create attr group\n");
}
return ret;
}
static int __exit es7243_i2c_remove(struct i2c_client *i2c) {
snd_soc_unregister_codec(&i2c->dev);
kfree(i2c_get_clientdata(i2c));
return 0;
}
static int es7243_i2c_detect(struct i2c_client *client,
struct i2c_board_info *info) {
struct i2c_adapter *adapter = client->adapter;
if (adapter->nr == ES7243_I2C_BUS_NUM) {
if (client->addr == 0x10) {
strlcpy(info->type, "MicArray_3", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x11) {
strlcpy(info->type, "MicArray_2", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x12) {
strlcpy(info->type, "MicArray_1", I2C_NAME_SIZE);
return 0;
} else if (client->addr == 0x13) {
strlcpy(info->type, "MicArray_0", I2C_NAME_SIZE);
return 0;
}
}
return -ENODEV;
}
static const unsigned short es7243_i2c_addr[] = {
#if ES7243_CHANNELS_MAX > 0
0x13,
#endif
#if ES7243_CHANNELS_MAX > 2
0x11,
#endif
#if ES7243_CHANNELS_MAX > 4
0x12,
#endif
#if ES7243_CHANNELS_MAX > 6
0x10,
#endif
I2C_CLIENT_END,
};
/*
* device tree source or i2c_board_info both use to transfer hardware
* information to linux kernel, use one of them wil be OK
*/
static struct i2c_board_info es7243_i2c_board_info[] = {
#if ES7243_CHANNELS_MAX > 0
{
I2C_BOARD_INFO("MicArray_0", 0x13),
}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{
I2C_BOARD_INFO("MicArray_1", 0x11),
}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{
I2C_BOARD_INFO("MicArray_2", 0x12),
}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{
I2C_BOARD_INFO("MicArray_3", 0x10),
}, // es7243_3
#endif
};
static const struct i2c_device_id es7243_i2c_id[] = {
#if ES7243_CHANNELS_MAX > 0
{"MicArray_0", 0}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{"MicArray_1", 1}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{"MicArray_2", 2}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{"MicArray_3", 3}, // es7243_3
#endif
{}};
MODULE_DEVICE_TABLE(i2c, es7243_i2c_id);
static const struct of_device_id es7243_dt_ids[] = {
#if ES7243_CHANNELS_MAX > 0
{
.compatible = "MicArray_0",
}, // es7243_0
#endif
#if ES7243_CHANNELS_MAX > 2
{
.compatible = "MicArray_1",
}, // es7243_1
#endif
#if ES7243_CHANNELS_MAX > 4
{
.compatible = "MicArray_2",
}, // es7243_2
#endif
#if ES7243_CHANNELS_MAX > 6
{
.compatible = "MicArray_3",
}, // es7243_3
#endif
};
MODULE_DEVICE_TABLE(of, es7243_dt_ids);
static struct i2c_driver es7243_i2c_driver = {
.driver =
{
.name = "es7243",
.owner = THIS_MODULE,
#if ES7243_MATCH_DTS_EN
.of_match_table = es7243_dt_ids,
#endif
},
.probe = es7243_i2c_probe,
.remove = __exit_p(es7243_i2c_remove),
.class = I2C_CLASS_HWMON,
.id_table = es7243_i2c_id,
#if !ES7243_MATCH_DTS_EN
.address_list = es7243_i2c_addr,
.detect = es7243_i2c_detect,
#endif
};
static int __init es7243_modinit(void) {
int ret, i;
struct i2c_adapter *adapter;
struct i2c_client *client;
printk("%s enter es7243\n", __func__);
// i2c_new_device(adapter, &tlv320_i2c_board_info[i]);
adapter = i2c_get_adapter(ES7243_I2C_BUS_NUM);
if (!adapter) {
printk("i2c_get_adapter() fail!\n");
return -ENODEV;
}
printk("%s() begin0000", __func__);
for (i = 0; i < ES7243_CHANNELS_MAX / 2; i++) {
client = i2c_new_device(adapter, &es7243_i2c_board_info[i]);
printk("%s() i2c_new_device, type:0x%x, addr:0x%x\n", __func__,
es7243_i2c_board_info[i].type, es7243_i2c_board_info[i].addr);
if (!client)
return -ENODEV;
}
i2c_put_adapter(adapter);
ret = i2c_add_driver(&es7243_i2c_driver);
if (ret != 0)
pr_err("Failed to register es7243 i2c driver : %d \n", ret);
return ret;
}
module_init(es7243_modinit);
static void __exit es7243_exit(void) {
//#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&es7243_i2c_driver);
//#endif
}
module_exit(es7243_exit);
MODULE_DESCRIPTION("ASoC ES7243 audio adc driver");
MODULE_AUTHOR(
"David Yang <yangxiaohua@everest-semi.com> / info@everest-semi.com");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,34 @@
/*
* ALSA SoC ES7243 codec driver
*
* Author: David Yang, <yangxiaohua@everest-semi.com>
* or
* <info@everest-semi.com>
* Copyright: (C) 2017 Everest Semiconductor Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _ES7243_H
#define _ES7243_H
/* Codec TLV320AIC23 */
#define ES7243_MODECFG_REG00 0x00
#define ES7243_SDPFMT_REG01 0x01
#define ES7243_LRCDIV_REG02 0x02
#define ES7243_BCKDIV_REG03 0x03
#define ES7243_CLKDIV_REG04 0x04
#define ES7243_MUTECTL_REG05 0x05
#define ES7243_STATECTL_REG06 0x06
#define ES7243_ANACTL0_REG07 0x07
#define ES7243_ANACTL1_REG08 0x08
#define ES7243_ANACTL2_REG09 0x09
#define ES7243_ANACHARG_REG0A 0x0A
#define ES7243_INISTATE_REG0B 0x0B
#define ES7243_BIAS_REG0C 0x0C
#define ES7243_STMOSR_REG0D 0x0D
#define ES7243_CHIPID_REG0E 0x0E
#endif /* _ES7243_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
#ifndef _AD82584F_H
#define _AD82584F_H
#define MVOL 0x03
#define C1VOL 0x04
#define C2VOL 0x05
#define CFADDR 0x1d
#define A1CF1 0x1e
#define A1CF2 0x1f
#define A1CF3 0x20
#define CFUD 0x2d
#define AD82584F_REGISTER_COUNT 0x86
#define AD82584F_RAM_TABLE_COUNT 0x80
struct ad82584f_platform_data {
int reset_pin;
int amp_en;
};
#endif

View File

@ -21,7 +21,7 @@
* o Add more codecs and platforms to ensure good API coverage. * o Add more codecs and platforms to ensure good API coverage.
* o Support TDM on PCM and I2S * o Support TDM on PCM and I2S
*/ */
#define DEBUG
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
@ -985,6 +985,8 @@ struct snd_soc_dai *snd_soc_find_dai(
if (dlc->name && strcmp(component->name, dlc->name)) if (dlc->name && strcmp(component->name, dlc->name))
continue; continue;
list_for_each_entry(dai, &component->dai_list, list) { list_for_each_entry(dai, &component->dai_list, list) {
if(dai && dai->name)
printk("Wzj,snd_soc_find_dai cur:%s\n", dai->name);
if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)) if (dlc->dai_name && strcmp(dai->name, dlc->dai_name))
continue; continue;
@ -3407,6 +3409,8 @@ int snd_soc_register_codec(struct device *dev,
dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",
codec->component.name); codec->component.name);
printk("ASoC: Registered codec '%s'\n",
codec->component.name);
return 0; return 0;
err_cleanup: err_cleanup:

View File

@ -834,6 +834,7 @@ static int sunxi_daudio_set_clkdiv(struct snd_soc_dai *dai, int clk_id,
else else
/* PCM mode */ /* PCM mode */
div_ratio = clk_div / sunxi_daudio->pdata->pcm_lrck_period; div_ratio = clk_div / sunxi_daudio->pdata->pcm_lrck_period;
printk("0.0000...sunxi_daudio_set_clkdiv...div_ratio=%d,clk_div=%d\n",div_ratio,clk_div);
switch (div_ratio) { switch (div_ratio) {
case 1: case 1:

View File

@ -90,15 +90,15 @@ define Package/$(PKG_NAME)/install
$(INSTALL_BIN) ./backuplocalfiles.sh $(1)/usr/sbin/ $(INSTALL_BIN) ./backuplocalfiles.sh $(1)/usr/sbin/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME)/modules/hardware/mcu_leds/mcu_ota $(TOPDIR)/prebuilt/r16/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME)/modules/hardware/mcu_leds/mcu_ota $(TOPDIR)/prebuilt/r16/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME)/nembd/evdev/bin/netease_keytest $(1)/usr/sbin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME)/nembd/evdev/bin/netease_keytest $(1)/usr/sbin/
$(INSTALL_BIN) ./netease.init $(1)/etc/init.d/netease_services # $(INSTALL_BIN) ./netease.init $(1)/etc/init.d/netease_services
$(INSTALL_BIN) ./neteasewifi.init $(1)/etc/init.d/netease_wifi_service # $(INSTALL_BIN) ./neteasewifi.init $(1)/etc/init.d/netease_wifi_service
# $(INSTALL_BIN) ./neteasevoice.init $(1)/etc/init.d/netease_voice_service # $(INSTALL_BIN) ./neteasevoice.init $(1)/etc/init.d/netease_voice_service
# $(INSTALL_BIN) ./neteaseplayer.init $(1)/etc/init.d/netease_player_service # $(INSTALL_BIN) ./neteaseplayer.init $(1)/etc/init.d/netease_player_service
$(INSTALL_BIN) ./neteasemanufacture_cc.init $(1)/etc/init.d/netease_cc_manufacture_service # $(INSTALL_BIN) ./neteasemanufacture_cc.init $(1)/etc/init.d/netease_cc_manufacture_service
$(INSTALL_BIN) ./neteasemanufacture_mcu.init $(1)/etc/init.d/netease_mcu_manufacture_service # $(INSTALL_BIN) ./neteasemanufacture_mcu.init $(1)/etc/init.d/netease_mcu_manufacture_service
$(INSTALL_BIN) ./neteasemanufacture_rf.init $(1)/etc/init.d/netease_rf_manufacture_service # $(INSTALL_BIN) ./neteasemanufacture_rf.init $(1)/etc/init.d/netease_rf_manufacture_service
# $(INSTALL_BIN) ./neteasecc.init $(1)/etc/init.d/netease_cc_service # $(INSTALL_BIN) ./neteasecc.init $(1)/etc/init.d/netease_cc_service
$(INSTALL_BIN) ./neteasebt.init $(1)/etc/init.d/netease_bt_service # $(INSTALL_BIN) ./neteasebt.init $(1)/etc/init.d/netease_bt_service
$(INSTALL_DATA) mcu/* $(1)/usr/share/golang/mcu/ $(INSTALL_DATA) mcu/* $(1)/usr/share/golang/mcu/
$(INSTALL_DATA) vol_adc.config $(1)/usr/share/golang/ $(INSTALL_DATA) vol_adc.config $(1)/usr/share/golang/
# $(INSTALL_DATA) ./ca-certificates.crt $(1)/etc/ssl/certs/ # $(INSTALL_DATA) ./ca-certificates.crt $(1)/etc/ssl/certs/

View File

@ -57,10 +57,18 @@ static int voice_major;
static int voice_status; static int voice_status;
static double voice_confidence; static double voice_confidence;
static VoiceSessionStatus vss = VoiceSession_Init; static VoiceSessionStatus vss = VoiceSession_Init;
static WorkMode wm = WorkMode_R311_PV1;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Function Definitions ** Function Definitions
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
void setWorkMode(WorkMode mode) {
wm = mode;
}
WorkMode getWorkMode() {
return wm;
}
void setVss(VoiceSessionStatus st) { vss = st; } void setVss(VoiceSessionStatus st) { vss = st; }
VoiceSessionStatus getVss() { return vss; } VoiceSessionStatus getVss() { return vss; }

View File

@ -117,7 +117,7 @@ int queue_write(audio_queue_t *queue, char data[], int dataLen) {
pthread_mutex_lock(&(queue->mutex)); pthread_mutex_lock(&(queue->mutex));
if (queue_left_asyn(queue) < dataLen) { if (queue_left_asyn(queue) < dataLen) {
pthread_mutex_unlock(&(queue->mutex)); pthread_mutex_unlock(&(queue->mutex));
n_error("queue_left_asyn queue < dataLen \n"); n_error("queue_left_asyn queue(%d) < dataLen(%d) \n",queue_left_asyn(queue), dataLen);
LOG_EX(LOG_Error, "ALSA Queue: queue_left_asyn queue < dataLen \n"); LOG_EX(LOG_Error, "ALSA Queue: queue_left_asyn queue < dataLen \n");
//return false; //return false;
queue_reset(queue); queue_reset(queue);
@ -153,13 +153,13 @@ int queue_read(audio_queue_t *queue, char **data) {
if (queue == NULL || data == NULL) { if (queue == NULL || data == NULL) {
return 0; return 0;
} }
// printf("queue_read pthread_cond_wait begin\n"); //printf("queue_read pthread_cond_wait begin\n");
native_event_wait(queue->sync_event, 0x7fffffff); native_event_wait(queue->sync_event, 0x7fffffff);
pthread_mutex_lock(&(queue->mutex)); pthread_mutex_lock(&(queue->mutex));
queueBase = (char *)(queue + 1); queueBase = (char *)(queue + 1);
begin = &((queueBase)[queue->front]); begin = &((queueBase)[queue->front]);
queueLen = queue_len_asyn(queue); queueLen = queue_len_asyn(queue);
// printf("queue_read queueLen %d\n", queueLen); //printf("queue_read queueLen %d\n", queueLen);
temp_buff = (char *)malloc(queueLen); temp_buff = (char *)malloc(queueLen);
if (NULL == temp_buff) { if (NULL == temp_buff) {

View File

@ -26,6 +26,12 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
/* ------------------------------------------------------------------------
** Defines
** ------------------------------------------------------------------------ */
#define BOARD_DMIC
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Types ** Types
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
@ -51,6 +57,10 @@ typedef enum {
VoiceSession_Created = 2 VoiceSession_Created = 2
} VoiceSessionStatus; } VoiceSessionStatus;
typedef enum {
WorkMode_R311_PV1 = 0
} WorkMode;
void setVss(VoiceSessionStatus st); void setVss(VoiceSessionStatus st);
VoiceSessionStatus getVss(); VoiceSessionStatus getVss();
@ -86,6 +96,9 @@ void setVoiceConfidence(double voiceConfidence);
double getVoiceConfidence(); double getVoiceConfidence();
void resetAdc(); void resetAdc();
void setWorkMode(WorkMode mode);
WorkMode getWorkMode();
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif /* C++ */ #endif /* C++ */

View File

@ -46,7 +46,7 @@ enum {
#endif #endif
#ifdef NETEASE_DEBUG #ifdef NETEASE_DEBUG
#define n_debug(fmt, arg...) printf(fmt, ##arg) #define n_debug(fmt, arg...) do{printf(fmt, ##arg);}while(0)
#else #else
#define n_debug(fmt, arg...) \ #define n_debug(fmt, arg...) \
do { \ do { \

View File

@ -0,0 +1,135 @@
#ifndef FORMATS_H
#define FORMATS_H 1
#include <sys/types.h>
#include <endian.h>
#include <byteswap.h>
/* Definitions for .VOC files */
#define VOC_MAGIC_STRING "Creative Voice File\x1A"
#define VOC_ACTUAL_VERSION 0x010A
#define VOC_SAMPLESIZE 8
#define VOC_MODE_MONO 0
#define VOC_MODE_STEREO 1
#define VOC_DATALEN(bp) ((u_long)(bp->datalen) | \
((u_long)(bp->datalen_m) << 8) | \
((u_long)(bp->datalen_h) << 16) )
typedef struct voc_header {
u_char magic[20]; /* must be MAGIC_STRING */
u_short headerlen; /* Headerlength, should be 0x1A */
u_short version; /* VOC-file version */
u_short coded_ver; /* 0x1233-version */
} VocHeader;
typedef struct voc_blocktype {
u_char type;
u_char datalen; /* low-byte */
u_char datalen_m; /* medium-byte */
u_char datalen_h; /* high-byte */
} VocBlockType;
typedef struct voc_voice_data {
u_char tc;
u_char pack;
} VocVoiceData;
typedef struct voc_ext_block {
u_short tc;
u_char pack;
u_char mode;
} VocExtBlock;
/* Definitions for Microsoft WAVE format */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
#define LE_SHORT(v) (v)
#define LE_INT(v) (v)
#define BE_SHORT(v) bswap_16(v)
#define BE_INT(v) bswap_32(v)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define COMPOSE_ID(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
#define LE_SHORT(v) bswap_16(v)
#define LE_INT(v) bswap_32(v)
#define BE_SHORT(v) (v)
#define BE_INT(v) (v)
#else
#error "Wrong endian"
#endif
/* Note: the following macros evaluate the parameter v twice */
#define TO_CPU_SHORT(v, be) \
((be) ? BE_SHORT(v) : LE_SHORT(v))
#define TO_CPU_INT(v, be) \
((be) ? BE_INT(v) : LE_INT(v))
#define WAV_RIFF COMPOSE_ID('R','I','F','F')
#define WAV_RIFX COMPOSE_ID('R','I','F','X')
#define WAV_WAVE COMPOSE_ID('W','A','V','E')
#define WAV_FMT COMPOSE_ID('f','m','t',' ')
#define WAV_DATA COMPOSE_ID('d','a','t','a')
/* WAVE fmt block constants from Microsoft mmreg.h header */
#define WAV_FMT_PCM 0x0001
#define WAV_FMT_IEEE_FLOAT 0x0003
#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092
#define WAV_FMT_EXTENSIBLE 0xfffe
/* Used with WAV_FMT_EXTENSIBLE format */
#define WAV_GUID_TAG "\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
/* it's in chunks like .voc and AMIGA iff, but my source say there
are in only in this combination, so I combined them in one header;
it works on all WAVE-file I have
*/
typedef struct {
u_int magic; /* 'RIFF' */
u_int length; /* filelen */
u_int type; /* 'WAVE' */
} WaveHeader;
typedef struct {
u_short format; /* see WAV_FMT_* */
u_short channels;
u_int sample_fq; /* frequence of sample */
u_int byte_p_sec;
u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
u_short bit_p_spl; /* 8, 12 or 16 bit */
} WaveFmtBody;
typedef struct {
WaveFmtBody format;
u_short ext_size;
u_short bit_p_spl;
u_int channel_mask;
u_short guid_format; /* WAV_FMT_* */
u_char guid_tag[14]; /* WAV_GUID_TAG */
} WaveFmtExtensibleBody;
typedef struct {
u_int type; /* 'data' */
u_int length; /* samplecount */
} WaveChunkHeader;
/* Definitions for Sparc .au header */
#define AU_MAGIC COMPOSE_ID('.','s','n','d')
#define AU_FMT_ULAW 1
#define AU_FMT_LIN8 2
#define AU_FMT_LIN16 3
typedef struct au_header {
u_int magic; /* '.snd' */
u_int hdr_size; /* size of header (min 24) */
u_int data_size; /* size of data */
u_int encoding; /* see to AU_FMT_XXXX */
u_int sample_rate; /* sample rate */
u_int channels; /* number of channels (voices) */
} AuHeader;
#endif /* FORMATS */

View File

@ -29,6 +29,7 @@ extern "C" {
** Types ** Types
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
typedef void* REACORD_HANDLE; typedef void* REACORD_HANDLE;
typedef void (*recordrecord_audio_fn)(const void *audio, unsigned int audio_len, int err_code);
typedef void (*record_audio_fn)(const void *audio, unsigned int audio_len, int err_code); typedef void (*record_audio_fn)(const void *audio, unsigned int audio_len, int err_code);
@ -39,13 +40,29 @@ typedef struct _RecordData{
audio_queue_t *queue; audio_queue_t *queue;
char *queue_buff; char *queue_buff;
char *buffer; char *buffer;
int buff_size;
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
record_audio_fn cb; record_audio_fn cb;
void *user_data; void *user_data;
pthread_t tid_pcm_read; pthread_t tid_pcm_read;
pthread_t tid_queue_read; pthread_t tid_queue_read;
int runing; int runing;
int backupfilefd;
int finalfilefd;
struct pcm_config *pcm_cfg;
struct pcm_config *adc;
size_t significant_bits_per_sample;
size_t bits_per_sample;
size_t bits_per_frame;
snd_pcm_format_t format;
size_t chunk_bytes;
size_t chunk_size;
size_t buff_size;
size_t buffer_time;
size_t period_time;
size_t buffer_frames;
size_t period_frames;
}RecordData; }RecordData;
struct pcm_config { struct pcm_config {
@ -56,11 +73,17 @@ struct pcm_config {
unsigned int period_count; unsigned int period_count;
record_audio_fn audio_cb; record_audio_fn audio_cb;
RecordData *recordata; RecordData *recordata;
RecordData *adc;
char *format;
char *backupfilename;
char *finalfilename;
int backupfile_waveformat;
}; };
int Neteasae_record_start(struct pcm_config *pcm_cfg); int Neteasae_record_start(struct pcm_config *pcm_cfg);
void Netease_record_stop(struct pcm_config *pcm_cfg); void Netease_record_stop(struct pcm_config *pcm_cfg);
void device_list(void);
void pcm_list(void);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -29,10 +29,12 @@ when who why
#include "srcwsapi.h" #include "srcwsapi.h"
#include "uvdbus/smart_sound.h" #include "uvdbus/smart_sound.h"
#include "yunxin.h" #include "yunxin.h"
#include <getopt.h>
#include <jansson.h> #include <jansson.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <uvdbus/fifo.h> #include <uvdbus/fifo.h>
#include <uvdbus/log.h> #include <uvdbus/log.h>
@ -46,20 +48,10 @@ when who why
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Macros ** Macros
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
#define BACKUP_ORIG_AUDIO
//#define BACKUP_FINAL_AUDIO
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Defines ** Defines
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
#ifdef BACKUP_ORIG_AUDIO
#define ORIG_AUDIO_FILENAME "/mnt/UDISK/origaudio.pcm"
static int fd_audio_orig;
#endif
#ifdef BACKUP_FINAL_AUDIO
static int fd_audio_final;
#endif
//#define ENABLE_OEM_DBUS //#define ENABLE_OEM_DBUS
@ -73,7 +65,8 @@ static int fd_audio_final;
** Global Variable Definitions ** Global Variable Definitions
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
// unsigned int g_bIsUsedTestServer; // unsigned int g_bIsUsedTestServer;
static int in_aborting = 0;
static int justrecord = 0;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Functions ** Functions
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
@ -87,10 +80,26 @@ const char *g_fmaeCfgPath = "/usr/share/fmae_res/config.ini";
CAEDATA *caeconfig = NULL; CAEDATA *caeconfig = NULL;
#endif #endif
struct pcm_config recordconfig; struct pcm_config recordconfig = {0};
struct audio_bypass *audiobypassconfig = NULL; struct audio_bypass *audiobypassconfig = NULL;
static char been_wakedup = 0; static char been_wakedup = 0;
static long parse_long(const char *str, int *err)
{
long val;
char *endptr;
errno = 0;
val = strtol(str, &endptr, 0);
if (errno != 0 || *endptr != '\0')
*err = -1;
else
*err = 0;
return val;
}
#if USED_NETEASE_DC #if USED_NETEASE_DC
static struct kfifo g_AudioCacheBuf; static struct kfifo g_AudioCacheBuf;
// static DECLARE_KFIFO(g_AudioCacheBuf, unsigned char, WAKE_CACHE_DATA_SIZE); // static DECLARE_KFIFO(g_AudioCacheBuf, unsigned char, WAKE_CACHE_DATA_SIZE);
@ -221,11 +230,13 @@ int Duilite_doa_cb(void *userdata, int type, char *msg, int len) {
} }
int Duilite_beforming_cb(void *userdata, int type, char *msg, int len) { int Duilite_beforming_cb(void *userdata, int type, char *msg, int len) {
int fd;
size_t hasWritten;
if (type == DUILITE_MSG_TYPE_BINARY) { if (type == DUILITE_MSG_TYPE_BINARY) {
// n_debug("Get beforming binary data:%d\n", len); if (recordconfig.recordata && recordconfig.recordata->finalfilefd > 0) {
#ifdef BACKUP_FINAL_AUDIO write(recordconfig.recordata->finalfilefd, msg, len);
write(fd_audio_final, msg, len); }
#endif
if (!!audiobypassconfig) { if (!!audiobypassconfig) {
Netease_audiobypass_write(audiobypassconfig, msg, len); Netease_audiobypass_write(audiobypassconfig, msg, len);
} }
@ -272,6 +283,7 @@ static void CAEAudioCb(const void *audioData, unsigned int audioLen, int param1,
static void record_audio_cb(const void *audio, unsigned int audio_len, static void record_audio_cb(const void *audio, unsigned int audio_len,
int err_code) { int err_code) {
unsigned long long cachetime; unsigned long long cachetime;
#ifdef DEBUG_WASTE_TIME #ifdef DEBUG_WASTE_TIME
Netease_caltime(&cachetime, 1); Netease_caltime(&cachetime, 1);
#endif #endif
@ -280,11 +292,6 @@ static void record_audio_cb(const void *audio, unsigned int audio_len,
int ret = 0; int ret = 0;
#endif #endif
#ifdef BACKUP_ORIG_AUDIO
// n_debug("Begin to write audio, size:%d\n", audio_len);
write(fd_audio_orig, audio, audio_len);
return;
#endif
#if USED_NETEASE_FMAE #if USED_NETEASE_FMAE
if (1) { if (1) {
#elif USED_NETEASE_DUILITE #elif USED_NETEASE_DUILITE
@ -499,23 +506,153 @@ void LogFunc(int logLevel, const char *log, void *userData) {
IHW_LogRawString(logLevel, (char *)log); IHW_LogRawString(logLevel, (char *)log);
} }
static void signal_handler(int sig) {
if (in_aborting)
return;
in_aborting = 1;
n_debug("Aborted by signal:%d, %s\n", sig, strsignal(sig));
Netease_record_stop(&recordconfig);
signal(sig, SIG_DFL);
}
static void usage() {
printf(
"Usage:\n"
"-h, --help help\n"
"-l, --list-devices list all soundcards and digital audio "
"devices\n"
"-L, --list-pcms list device names\n"
"-w, --work-mode=# work mode: 0: r311_pv1\n"
"-f, --list-format list all format in alsa\n"
"-r, --just-record Only record voice to file\n"
"-t, --type=# sample format (case insensitive): raw,wav\n"
"--rawfile=# record raw data to filepath\n"
"--finalfile=# record duilite output to filepath\n");
}
enum {
OPT_RAW_FILE = 1,
OPT_FINAL_FILE
};
void main(int argc, char **argv) { void main(int argc, char **argv) {
int ret; int ret, c, option_index, err,tmp;
unsigned int card = 1; char *rawfile = "/dev/null";
unsigned int device = 0; char *finalfile = "/dev/null";
unsigned int channels = 2; static const char short_options[] = "hlt:w:Lfr";
unsigned int rate = 96000; static const struct option long_options[] = {
{"help", 0, 0, 'h'},
{"list-devices", 0, 0, 'l'},
{"list-pcms", 0, 0, 'L'},
{"list-format", 0, 0, 'f'},
{"just-record", 0, 0, 'r'},
{"rawfile", 1, 0, OPT_RAW_FILE},
{"finalfile", 1, 0, OPT_FINAL_FILE},
{"type", 1, 0, 't'},
{"work-mode", 1, 0, 'w'},
{0, 0, 0, 0}};
// unsigned int frames; recordconfig.backupfile_waveformat = 1;
unsigned int period_size = 1535; recordconfig.audio_cb = record_audio_cb;
unsigned int period_count = 4; setWorkMode(WorkMode_R311_PV1);
char sound_device_name[30]; if (argc == 1) {
printf("Not enough arg!\n");
usage();
return;
}
while ((c = getopt_long(argc, argv, short_options, long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
usage();
return;
case 'l':
device_list();
return;
case 'L':
pcm_list();
return;
case 'r':
justrecord = 1;
break;
case 't':
if (strcasecmp(optarg, "wav") == 0) {
recordconfig.backupfile_waveformat = 1;
} else if (strcasecmp(optarg, "raw") == 0) {
recordconfig.backupfile_waveformat = 0;
}
printf("Wave format:%d\n", recordconfig.backupfile_waveformat);
break;
case 'w':
tmp = parse_long(optarg, &err);
if (err < 0) {
printf("invalid work mode!%s\n", optarg);
return;
} else {
setWorkMode((WorkMode)tmp);
}
break;
case OPT_RAW_FILE:
rawfile = optarg;
printf("Raw file:%s\n", optarg);
break;
case OPT_FINAL_FILE:
finalfile = optarg;
printf("Final file:%s\n", optarg);
break;
default:
printf("Unknow cmd!(%d)\n", c);
usage();
exit(0);
}
}
printf("parse arg end!\n");
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGABRT, signal_handler);
// Base module init
BaseInit();
printf("Work mode:%d\n", getWorkMode());
// resetAdc();
if (justrecord == 1) {
if (rawfile == NULL && finalfile == NULL) {
printf("Must input rawfile or finalfile!\n");
return;
}
if (rawfile != NULL) {
recordconfig.backupfilename = rawfile;
printf("Will record raw to file:%s\n", rawfile);
}
if (finalfile != NULL) {
recordconfig.finalfilename = finalfile;
printf("Will record final data to file:%s\n", finalfile);
}
recordconfig.audio_cb = NULL;
Neteasae_record_start(&recordconfig);
while (1)
usleep(1000000);
}
#ifdef ENABLE_OEM_DBUS #ifdef ENABLE_OEM_DBUS
ret = Netease_dbus_oem_init(DBusMessageCb); ret = Netease_dbus_oem_init(DBusMessageCb);
#else #else
// ret = Netease_Dbus_Init(DBusMessageCb); ret = Netease_Dbus_Init(DBusMessageCb);
#endif #endif
if (NETEASE_SUCCESS == ret) { if (NETEASE_SUCCESS == ret) {
n_debug("Dbus init success\n"); n_debug("Dbus init success\n");
@ -546,42 +683,6 @@ void main(int argc, char **argv) {
} }
#endif #endif
snprintf(sound_device_name, sizeof(sound_device_name), "plughw:%u,%u", card,
device);
recordconfig.device_name = sound_device_name;
recordconfig.channels = channels;
recordconfig.rate = rate;
recordconfig.period_size = period_size;
recordconfig.period_count = period_count;
recordconfig.audio_cb = record_audio_cb;
// todo write something
printf("++++++++++++++++++++++++++\n");
printf("device name is %s\n", recordconfig.device_name);
printf("Channle is %d\n", recordconfig.channels);
printf("rate name is %d\n", recordconfig.rate);
printf("period_size name is %d\n", recordconfig.period_size);
printf("++++++++++++++++++++++++++\n");
n_debug("Begin to init netease_voice modules!\n");
extern void listAlsaDev();
resetAdc();
listAlsaDev();
#ifdef BACKUP_ORIG_AUDIO
fd_audio_orig = open(argv[1], O_CREAT | O_APPEND | O_RDWR);
n_debug("Open file: %s, fd:%d\n", argv[1], fd_audio_orig);
Neteasae_record_start(&recordconfig);
while (1)
usleep(1000000);
#endif
#ifdef BACKUP_FINAL_AUDIO
fd_audio_final = open("/tmp/finalaudio", O_CREAT | O_APPEND | O_RDWR);
#endif
// Base module init
BaseInit();
#if USED_NETEASE_FMAE #if USED_NETEASE_FMAE
ret = Netease_audiobypass_init(&audiobypassconfig, NULL, ret = Netease_audiobypass_init(&audiobypassconfig, NULL,
AUDIO_BYPASS_CHANNEL_MSC_IAT); AUDIO_BYPASS_CHANNEL_MSC_IAT);
@ -666,10 +767,27 @@ void main(int argc, char **argv) {
#ifdef ENABLE_OEM_DBUS #ifdef ENABLE_OEM_DBUS
pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL); pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL);
#else #else
// pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL); pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
#endif #endif
// Netease_yunxin_test(); // Netease_yunxin_test();
#if 0
while (1) {
if (1 == Netease_nduilite_init(Duilite_wakeup_cb, Duilite_doa_cb,
Duilite_beforming_cb, Duilite_vad_cb)) {
n_toast("Nduilite init success, exit!\n");
break;
} else {
n_toast("Nduilite init fail, sleep and redo!\n");
usleep(1000000);
}
}
while (1)
usleep(1000000);
#endif
while (1) { while (1) {
if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) { if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) {
// n_toast("Get args frome cc\n"); // n_toast("Get args frome cc\n");

View File

@ -352,6 +352,29 @@ int Netease_nduilite_init(duilite_callback wakeup_callback,
return 1; return 1;
} }
void Dmic_data_convert(const void *audioData, unsigned int audio_len) {
short *p = audioData;
short tmp;
int bitPerChan = 16;
int chanNum = 8;
//16bit 8 channel, 0,1 is null
if (audio_len%(bitPerChan*chanNum/8) != 0) {
n_error("Input data len(%d) error, not full frame!", audio_len);
}
while(p < (audioData+audio_len)) {
p[0] = p[2];
p[1] = p[3];
p[2] = p[4];
p[3] = p[5];
p[4] = p[6];
p[5] = p[7];
p[6] = 0x0000;
p[7] = 0x0000;
p += 8;
}
}
void Netease_nduilite_writeaudio(const void *audioData, void Netease_nduilite_writeaudio(const void *audioData,
unsigned int audio_len) { unsigned int audio_len) {
int len = 0; int len = 0;
@ -372,6 +395,10 @@ void Netease_nduilite_writeaudio(const void *audioData,
return; return;
} }
//n_debug("Write nduilite data, len:%d\n", audio_len);
ret = duilite_fespa_feed(fespa, audioData, audio_len);
#if 0
newbuf = (char *)malloc(audio_len + 60); newbuf = (char *)malloc(audio_len + 60);
if (newbuf == NULL) { if (newbuf == NULL) {
@ -388,4 +415,5 @@ void Netease_nduilite_writeaudio(const void *audioData,
write(fd_audio_orig, newbuf, len); write(fd_audio_orig, newbuf, len);
#endif #endif
free(newbuf); free(newbuf);
#endif
} }

View File

@ -28,6 +28,8 @@ when who why
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "base.h"
#include "formats.h"
#include "record.h" #include "record.h"
#include "error.h" #include "error.h"
@ -35,6 +37,7 @@ when who why
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <stdint.h> #include <stdint.h>
#include <sys/stat.h>
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Macros ** Macros
@ -42,7 +45,7 @@ when who why
#define ALSA_PCM_NEW_HW_PARAMS_API #define ALSA_PCM_NEW_HW_PARAMS_API
#define AUDIO_QUEUE_BUFF_LEN (1024 * 10) #define AUDIO_QUEUE_BUFF_LEN (1024 * 10)
#define QUEUE_BUFF_MULTIPLE 1000 #define QUEUE_BUFF_MULTIPLE 100
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Types ** Types
@ -64,14 +67,40 @@ static Proc_CAEGetChannel api_cae_get_channel;
static Proc_CAESetShowLog api_cae_set_show_log; static Proc_CAESetShowLog api_cae_set_show_log;
static Proc_CAEDestroy api_cae_destroy; static Proc_CAEDestroy api_cae_destroy;
static off64_t fdcount = 0;
static snd_output_t *sndlog;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
** Function Definitions ** Function Definitions
** ------------------------------------------------------------------------ */ ** ------------------------------------------------------------------------ */
static void *QueueReadThread(void *param); static void *QueueReadThread(void *param);
static void *RecordThread(void *param); static void *RecordThread(void *param);
static ssize_t xwrite(int fd, const void *buf, size_t count);
static void record_audio_cb(const void *audio, unsigned int audio_len, static void record_audio_cb(const void *audio, unsigned int audio_len,
int err_code); int err_code);
void _record_stop(void *record_hd); void _record_stop(void *record_hd);
static void end_wave(int fd);
static void begin_wave(RecordData *record, int fd, size_t cnt);
void _record_stop(void *record_hd);
static int init_params(struct pcm_config *pcm_cfg, int init_queue);
/*
* make sure we write all bytes or return an error
*/
static ssize_t xwrite(int fd, const void *buf, size_t count) {
ssize_t written;
size_t offset = 0;
while (offset < count) {
written = write(fd, buf + offset, count - offset);
if (written <= 0)
return written;
offset += written;
};
return offset;
}
static void *QueueReadThread(void *param) { static void *QueueReadThread(void *param) {
RecordData *record = (RecordData *)param; RecordData *record = (RecordData *)param;
@ -83,7 +112,7 @@ static void *QueueReadThread(void *param) {
if (0 == readLen) { if (0 == readLen) {
// printf("queue_read readLen = 0\n"); // printf("queue_read readLen = 0\n");
// usleep(16000); // usleep(16000);
// continue; continue;
} }
if (record->buff_size != readLen) { if (record->buff_size != readLen) {
// printf("\nqueue_read readLen %d\n", readLen); // printf("\nqueue_read readLen %d\n", readLen);
@ -96,57 +125,380 @@ static void *QueueReadThread(void *param) {
return NULL; return NULL;
} }
static void *RecordThread(void *param) { static void do_test_position(RecordData *record) {
RecordData *record = (RecordData *)param; static long counter = 0;
int ret = 0; static time_t tmr = -1;
// cpu_set_t mask; time_t now;
n_toast("RecordThread record:%p, running:%d\n", record, record->runing); static float availsum, delaysum, samples;
// CPU_ZERO(&mask); static snd_pcm_sframes_t maxavail, maxdelay;
// CPU_SET(0,&mask); static snd_pcm_sframes_t minavail, mindelay;
// ret = sched_setaffinity(0, sizeof(mask), &mask); static snd_pcm_sframes_t badavail = 0, baddelay = 0;
// printf("sched_setaffinity return = %d\n", ret); snd_pcm_sframes_t outofrange;
while (!!record->runing) { snd_pcm_sframes_t avail, delay;
ret = snd_pcm_readi(record->handle, record->buffer, record->frames); int err;
// printf("snd_pcm_readi return = %d\n", ret); int test_coef = 8;
if (ret == -EPIPE) {
err = snd_pcm_avail_delay(record->handle, &avail, &delay);
if (err < 0)
return;
outofrange = (test_coef * (snd_pcm_sframes_t)record->frames) / 2;
if (avail > outofrange || avail < -outofrange || delay > outofrange ||
delay < -outofrange) {
badavail = avail;
baddelay = delay;
availsum = delaysum = samples = 0;
maxavail = maxdelay = 0;
minavail = mindelay = record->frames * 16;
fprintf(stderr,
"Suspicious buffer position (%li total): "
"avail = %li, delay = %li, buffer = %li\n",
++counter, (long)avail, (long)delay, (long)record->frames);
} else {
time(&now);
if (tmr == (time_t)-1) {
tmr = now;
availsum = delaysum = samples = 0;
maxavail = maxdelay = 0;
minavail = mindelay = record->frames * 16;
}
if (avail > maxavail)
maxavail = avail;
if (delay > maxdelay)
maxdelay = delay;
if (avail < minavail)
minavail = avail;
if (delay < mindelay)
mindelay = delay;
availsum += avail;
delaysum += delay;
samples++;
if (avail != 0 && now != tmr) {
fprintf(stderr,
"BUFPOS: avg%li/%li "
"min%li/%li max%li/%li (%li) (%li:%li/%li)\n",
(long)(availsum / samples), (long)(delaysum / samples),
(long)minavail, (long)mindelay, (long)maxavail,
(long)maxdelay, (long)record->frames, counter, badavail,
baddelay);
tmr = now;
}
}
}
static ssize_t pcm_read(RecordData *record) {
ssize_t r;
size_t result = 0;
size_t rcount = record->chunk_size;
size_t count = rcount;
char *data = record->buffer;
while (count > 0 && !!record->runing) {
r = snd_pcm_readi(record->handle, data, count);
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
n_debug("read data == EAGAIN\n");
snd_pcm_wait(record->handle, 50);
} else if (r == -EPIPE) {
/* EPIPE means overrun */ /* EPIPE means overrun */
fprintf(stderr, "overrun occurred/n"); fprintf(stderr, "overrun occurred/n");
LOG_EX(LOG_Error, "ALSA Read Data = -EPIPE\n"); LOG_EX(LOG_Error, "ALSA Read Data = -EPIPE\n");
snd_pcm_prepare(record->handle); snd_pcm_prepare(record->handle);
continue; continue;
} else if (ret < 0) { } else if (r < 0) {
fprintf(stderr, "error from read: %s/n", snd_strerror(ret)); fprintf(stderr, "error from read: %s/n", snd_strerror(r));
LOG_EX(LOG_Error, "ALSA Read Data Error: %s(%d)\n", snd_strerror(ret), ret); LOG_EX(LOG_Error, "ALSA Read Data Error: %s(%d)\n", snd_strerror(r),
record->cb(NULL, 0, ret); r);
return NULL; return 0;
} else if (ret != (int)record->frames) {
fprintf(stderr, "short read, read %d frames/n", ret);
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n", ret);
} }
queue_write(record->queue, record->buffer, record->buff_size); if (r > 0) {
result += r;
count -= r;
data += r * record->bits_per_frame / 8;
}
}
return result;
}
static void end_wave(int fd) { /* only close output */
WaveChunkHeader cd;
off64_t length_seek;
off64_t filelen;
u_int rifflen;
length_seek =
sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody);
cd.type = WAV_DATA;
cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
filelen = fdcount + 2 * sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
if (lseek64(fd, 4, SEEK_SET) == 4)
xwrite(fd, &rifflen, 4);
if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
xwrite(fd, &cd, sizeof(WaveChunkHeader));
if (fd != 1)
close(fd);
}
/* write a WAVE-header */
static void begin_wave(RecordData *record, int fd, size_t cnt) {
WaveHeader h;
WaveFmtBody f;
WaveChunkHeader cf, cd;
int bits;
u_int tmp;
u_short tmp2;
/* WAVE cannot handle greater than 32bit (signed?) int */
if (cnt == (size_t)-2)
cnt = 0x7fffff00;
bits = 8;
switch ((unsigned long)record->format) {
case SND_PCM_FORMAT_U8:
bits = 8;
break;
case SND_PCM_FORMAT_S16_LE:
bits = 16;
break;
case SND_PCM_FORMAT_S32_LE:
case SND_PCM_FORMAT_FLOAT_LE:
bits = 32;
break;
case SND_PCM_FORMAT_S24_LE:
case SND_PCM_FORMAT_S24_3LE:
bits = 24;
break;
default:
n_error("Wave doesn't support %s format..."),
snd_pcm_format_name(record->format);
return;
}
h.magic = WAV_RIFF;
tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) +
sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
h.length = LE_INT(tmp);
h.type = WAV_WAVE;
cf.type = WAV_FMT;
cf.length = LE_INT(16);
if (record->format == SND_PCM_FORMAT_FLOAT_LE)
f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT);
else
f.format = LE_SHORT(WAV_FMT_PCM);
f.channels = LE_SHORT(record->pcm_cfg->channels);
f.sample_fq = LE_INT(record->pcm_cfg->rate);
#if 0
tmp2 = (samplesize == 8) ? 1 : 2;
f.byte_p_spl = LE_SHORT(tmp2);
tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
#else
tmp2 = record->pcm_cfg->channels *
snd_pcm_format_physical_width(record->format) / 8;
f.byte_p_spl = LE_SHORT(tmp2);
tmp = (u_int)tmp2 * record->pcm_cfg->rate;
#endif
f.byte_p_sec = LE_INT(tmp);
f.bit_p_spl = LE_SHORT(bits);
cd.type = WAV_DATA;
cd.length = LE_INT(cnt);
if (xwrite(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
xwrite(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
xwrite(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
xwrite(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
n_error("write error");
return;
}
}
static void *RecordThread(void *param) {
RecordData *record = (RecordData *)param;
int ret = 0;
int i = 0;
long long max_file_size = 2147483648LL;
// cpu_set_t mask;
n_toast("RecordThread record:%p, running:%d\n", record, record->runing);
n_toast("record->pcm_cfg:%p\n", record->pcm_cfg);
n_toast("record->pcm_cfg->adc:%p\n", record->pcm_cfg->adc);
// CPU_ZERO(&mask);
// CPU_SET(0,&mask);
// ret = sched_setaffinity(0, sizeof(mask), &mask);
// printf("sched_setaffinity return = %d\n", ret);
if (record->backupfilefd > 0 &&
record->pcm_cfg->backupfile_waveformat > 0) {
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
fdcount = 0;
}
if (record->finalfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
}
while (!!record->runing) {
if (getWorkMode() == WorkMode_R311_PV1) {
if (pcm_read(record->pcm_cfg->adc) ==
record->pcm_cfg->adc->chunk_size) {
if (pcm_read(record) == record->chunk_size) {
// Write adc data to dmic data, in first two channel
for (i = 0; i < record->chunk_size; i++) {
// printf("copy from %p to %p, size:%d, frame:%d\n",
// (record->pcm_cfg->adc->buffer +
// i *
// record->pcm_cfg->adc->bits_per_frame
// / 8), (record->buffer + i *
// record->bits_per_frame / 8), 2 *
// record->significant_bits_per_sample /
// 8, i);
// ch:1-6 dmic
// ch:7-8 adc
memmove(
(void *)(record->buffer +
i * record->bits_per_frame / 8),
(void *)(record->buffer +
i * record->bits_per_frame / 8 +
2 * record->significant_bits_per_sample /
8),
6 * record->significant_bits_per_sample / 8);
// printf("copy to 0x%p, size:%d\n", (record->buffer +
// i * record->bits_per_frame / 8 +
// 6 * record->significant_bits_per_sample /
// 8), 2 * record->significant_bits_per_sample / 8);
memcpy(
(void *)(record->buffer +
i * record->bits_per_frame / 8 +
6 * record->significant_bits_per_sample /
8),
(void *)(record->pcm_cfg->adc->buffer +
i * record->pcm_cfg->adc->bits_per_frame /
8),
record->pcm_cfg->adc->bits_per_frame / 8);
// memcpy((void *)(record->buffer +
// i * record->bits_per_frame / 8),
// (void *)(record->pcm_cfg->adc->buffer +
// i *
// record->pcm_cfg->adc->bits_per_frame
// / 8),
// 2 * record->significant_bits_per_sample / 8);
}
if (record->backupfilefd > 0) {
xwrite(record->backupfilefd, record->buffer,
record->chunk_bytes);
fdcount += record->chunk_bytes;
}
queue_write(record->queue, record->buffer,
record->chunk_bytes);
} else {
fprintf(stderr, "short read, read %d frames/n", ret);
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n",
ret);
}
} else {
// read dmic data and throw
pcm_read(record);
printf("Read adc codec error!\n");
}
} else {
printf("Unknow work mode!\n");
exit(0);
}
}
if (record->backupfilefd > 0 &&
record->pcm_cfg->backupfile_waveformat > 0) {
end_wave(record->backupfilefd);
record->backupfilefd = 0;
n_debug("Write backup file end finish!\n");
} }
n_debug("RecordThread end, running:%d\n", record->runing); n_debug("RecordThread end, running:%d\n", record->runing);
return NULL; return NULL;
} }
static void show_available_sample_formats(snd_pcm_t *handle,
snd_pcm_hw_params_t *params) {
snd_pcm_format_t format;
fprintf(stderr, "Available formats:\n");
for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
fprintf(stderr, "- %s\n", snd_pcm_format_name(format));
}
}
int Neteasae_record_start(struct pcm_config *pcm_cfg) { int Neteasae_record_start(struct pcm_config *pcm_cfg) {
pthread_attr_t thread_attr;
struct sched_param thread_param;
struct pcm_config *tmp;
printf("Begin to init netease record!\n");
snd_output_stdio_attach(&sndlog, stderr, 0);
switch (getWorkMode()) {
case WorkMode_R311_PV1:
// dmic codec
pcm_cfg->device_name = "hw:1,0";
pcm_cfg->channels = 8;
pcm_cfg->rate = 16000;
pcm_cfg->period_size = 1535;
pcm_cfg->format = "S16_LE";
printf("Begin to init dmic!\n");
init_params(pcm_cfg, 1);
tmp = (struct pcm_config *)calloc(1, sizeof(struct pcm_config));
if (tmp == NULL) {
printf("alloc fail!\n");
exit(0);
} else {
printf("Begin to init adc codec!\n");
// adc codec
tmp->device_name = "hw:2,0";
tmp->channels = 2;
tmp->rate = 16000;
tmp->period_size = 1535;
tmp->format = "S16_LE";
init_params(tmp, 0);
}
pcm_cfg->adc = tmp->recordata;
pcm_cfg->recordata->adc = tmp;
pthread_attr_init(&thread_attr);
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedparam(&thread_attr, &thread_param);
pthread_create(&pcm_cfg->recordata->tid_pcm_read, &thread_attr,
RecordThread, (void *)pcm_cfg->recordata);
pthread_create(&pcm_cfg->recordata->tid_queue_read, NULL,
QueueReadThread, (void *)pcm_cfg->recordata);
break;
default:
printf("Unknow mode!\n");
exit(0);
}
}
static int init_params(struct pcm_config *pcm_cfg, int init_queue) {
int rc; int rc;
int size; int size;
int ret = NETEASE_SUCCESS; int ret = NETEASE_SUCCESS;
pthread_attr_t thread_attr;
struct sched_param thread_param;
snd_pcm_hw_params_t *params; snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
unsigned int val, val2; unsigned int val, val2;
int dir; int dir;
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
char *buffer; char *buffer;
struct stat statbuf;
RecordData *record = (RecordData *)malloc(sizeof(RecordData)); RecordData *record = (RecordData *)malloc(sizeof(RecordData));
if (NULL == record) { if (NULL == record) {
return NETEASE_ERROR_OUT_OF_MEMORY; printf("Malloc fail for record data!\n");
return NETEASE_ERROR_OUT_OF_MEMORY;
} }
pcm_cfg->recordata = record;
memset(record, 0, sizeof(RecordData)); memset(record, 0, sizeof(RecordData));
pcm_cfg->recordata = record;
record->pcm_cfg = pcm_cfg;
record->cb = pcm_cfg->audio_cb; record->cb = pcm_cfg->audio_cb;
//设置录音参数参数 //设置录音参数参数
@ -154,11 +506,24 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
SND_PCM_STREAM_CAPTURE, 0); SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) { if (rc < 0) {
n_error("unable to open pcm device: %s/n", snd_strerror(rc)); n_error("unable to open pcm device: %s/n", snd_strerror(rc));
ret = NETEASE_ERROR_OPEN_FILE; ret = NETEASE_ERROR_OPEN_FILE;
goto error; goto error;
} }
record->format = snd_pcm_format_value(pcm_cfg->format);
if (record->format == SND_PCM_FORMAT_UNKNOWN) {
n_error("Wrong format:%s\n", record->format);
ret = NETEASE_ERROR_FAIL;
goto error;
}
n_debug("Format:%s\n", snd_pcm_format_description(record->format));
n_debug("Rate %d Hz\n", pcm_cfg->rate);
n_debug("Channel %d\n", pcm_cfg->channels);
/* Allocate a hardware parameters object. */ /* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params); snd_pcm_hw_params_alloca(&params);
snd_pcm_sw_params_alloca(&swparams);
/* Fill it in with default values. */ /* Fill it in with default values. */
snd_pcm_hw_params_any(record->handle, params); snd_pcm_hw_params_any(record->handle, params);
@ -169,60 +534,127 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
SND_PCM_ACCESS_RW_INTERLEAVED); SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */ /* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(record->handle, params, SND_PCM_FORMAT_S24_LE); rc = snd_pcm_hw_params_set_format(record->handle, params, record->format);
if (rc < 0) {
n_error("Sample format non available!\n");
show_available_sample_formats(record->handle, params);
goto error;
}
/* Two channels (stereo) */ /* Two channels (stereo) */
snd_pcm_hw_params_set_channels(record->handle, params, pcm_cfg->channels); rc = snd_pcm_hw_params_set_channels(record->handle, params,
pcm_cfg->channels);
if (rc < 0) {
n_error("Channel count(%d) not available!\n", pcm_cfg->channels);
goto error;
}
/* 44100 bits/second sampling rate (CD quality) */ /* 44100 bits/second sampling rate (CD quality) */
val = pcm_cfg->rate; val = pcm_cfg->rate;
snd_pcm_hw_params_set_rate_near(record->handle, params, &val, &dir); snd_pcm_hw_params_set_rate_near(record->handle, params, &val, 0);
/* Set period size to frames. */ /* Set period size to frames. */
frames = pcm_cfg->period_size; // frames = pcm_cfg->period_size;
snd_pcm_hw_params_set_period_size_near(record->handle, params, &frames, // snd_pcm_hw_params_set_period_size_near(record->handle, params, &frames,
&dir); // 0);
record->frames = frames; snd_pcm_hw_params_get_buffer_time_max(params, &record->buffer_time, 0);
if (record->buffer_time > 500000) {
record->buffer_time = 500000;
}
record->period_time = record->buffer_time / 4;
n_debug("Buffer time:%d, period time:%d\n", record->buffer_time,
record->period_time);
snd_pcm_hw_params_set_period_time_near(record->handle, params,
&record->period_time, 0);
snd_pcm_hw_params_set_buffer_time_near(record->handle, params,
&record->buffer_time, 0);
snd_pcm_hw_params_get_period_size(params, &record->chunk_size, 0);
record->frames = record->chunk_size;
snd_pcm_hw_params_get_buffer_size(params, &record->buff_size);
n_debug("Buffer size:%d, period size:%d\n", record->buff_size,
record->chunk_size);
/* Write the parameters to the driver */ /* Write the parameters to the driver */
rc = snd_pcm_hw_params(record->handle, params); rc = snd_pcm_hw_params(record->handle, params);
if (rc < 0) { if (rc < 0) {
n_error("unable to set hw parameters: %s/n", snd_strerror(rc)); n_error("unable to set hw parameters: %s/n", snd_strerror(rc));
// snd_pcm_hw_dump(params, sndlog);
ret = NETEASE_ERROR_FAIL; ret = NETEASE_ERROR_FAIL;
goto error; goto error;
} }
// snd_pcm_hw_params_dump(params, stdout);
snd_pcm_dump(record->handle, sndlog);
/* Use a buffer large enough to hold one period */ /* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir); record->bits_per_sample = snd_pcm_format_physical_width(record->format);
size = frames * 8; /* 4 bytes/sample, 2 channels */ record->significant_bits_per_sample = snd_pcm_format_width(record->format);
record->buff_size = size; record->bits_per_frame = record->bits_per_sample * pcm_cfg->channels;
n_toast("frames=%ld,record->buff_size=%d\n", frames, record->buff_size); record->chunk_bytes = record->chunk_size * record->bits_per_frame / 8;
record->buffer = (char *)malloc(size);
n_debug("bits_per_frame=%d, channel=%d, chunk_bytes=%d\n",
record->bits_per_frame, pcm_cfg->channels, record->chunk_bytes);
n_debug(
"frames=%ld,record->buff_size=%d, quene multiple:%d, quene size:%d\n",
record->chunk_size, record->buff_size, QUEUE_BUFF_MULTIPLE,
QUEUE_BUFF_MULTIPLE * record->buff_size);
record->buffer = (char *)malloc(record->chunk_bytes);
if (NULL == record->buffer) { if (NULL == record->buffer) {
ret = NETEASE_ERROR_OUT_OF_MEMORY; ret = NETEASE_ERROR_OUT_OF_MEMORY;
goto error; goto error;
} }
record->queue_buff = if (init_queue > 0) {
(char *)malloc(sizeof(audio_queue_t) + size * QUEUE_BUFF_MULTIPLE + 1); record->queue_buff = (char *)malloc(
if (NULL == record->queue_buff) { sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
ret = NETEASE_ERROR_OUT_OF_MEMORY; if (NULL == record->queue_buff) {
ret = NETEASE_ERROR_OUT_OF_MEMORY;
goto error;
}
record->queue = queue_init(record->queue_buff,
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
} else {
record->queue_buff = NULL;
record->queue = NULL;
}
snd_pcm_sw_params_current(record->handle, swparams);
snd_pcm_sw_params_set_avail_min(record->handle, swparams,
record->chunk_size);
snd_pcm_sw_params_set_start_threshold(record->handle, swparams, 1);
snd_pcm_sw_params_set_stop_threshold(record->handle, swparams, 8000);
if (snd_pcm_sw_params(record->handle, swparams) < 0) {
n_error("unable to install sw params:");
snd_pcm_sw_params_dump(swparams, stdout);
goto error; goto error;
} }
record->queue =
queue_init(record->queue_buff, size * QUEUE_BUFF_MULTIPLE + 1);
pthread_attr_init(&thread_attr);
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedparam(&thread_attr, &thread_param);
record->runing = 1; record->runing = 1;
if (pcm_cfg->backupfilename != NULL) {
if (!lstat(pcm_cfg->backupfilename, &statbuf)) {
if (S_ISREG(statbuf.st_mode))
remove(pcm_cfg->backupfilename);
n_debug("Remove file:%s\n", pcm_cfg->backupfilename);
}
record->backupfilefd =
open(pcm_cfg->backupfilename, O_TRUNC | O_WRONLY | O_CREAT, 06444);
n_debug("Create backup file:%s, fd:%d\n", pcm_cfg->backupfilename,
record->backupfilefd);
}
if (pcm_cfg->finalfilename != NULL) {
if (!lstat(pcm_cfg->finalfilename, &statbuf)) {
if (S_ISREG(statbuf.st_mode))
remove(pcm_cfg->finalfilename);
n_debug("Remove file:%s\n", pcm_cfg->finalfilename);
}
record->finalfilefd =
open(pcm_cfg->finalfilename, O_TRUNC | O_WRONLY | O_CREAT, 06444);
n_debug("Create final file:%s, fd:%d\n", pcm_cfg->finalfilename,
record->finalfilefd);
}
n_toast("Record_start record :%p\n", record); n_toast("Record_start record :%p\n", record);
pthread_create(&record->tid_pcm_read, &thread_attr, RecordThread,
(void *)record);
pthread_create(&record->tid_queue_read, NULL, QueueReadThread,
(void *)record);
goto exit; goto exit;
@ -239,13 +671,12 @@ void _record_stop(void *record_hd) {
printf("\nrecord_stop in record:%p\n\n", record); printf("\nrecord_stop in record:%p\n\n", record);
if (NULL != record) { if (NULL != record) {
record->runing = 0; record->runing = 0;
if(NULL != record->tid_pcm_read) if (NULL != record->tid_pcm_read)
pthread_join(record->tid_pcm_read, NULL); pthread_join(record->tid_pcm_read, NULL);
if(NULL != record->tid_queue_read) if (NULL != record->tid_queue_read)
pthread_join(record->tid_queue_read, NULL); pthread_join(record->tid_queue_read, NULL);
if(NULL != record->handle) if (NULL != record->handle) {
{
snd_pcm_drain(record->handle); snd_pcm_drain(record->handle);
snd_pcm_close(record->handle); snd_pcm_close(record->handle);
} }
@ -253,15 +684,15 @@ void _record_stop(void *record_hd) {
if (NULL != record->queue) { if (NULL != record->queue) {
queue_destroy(record->queue); queue_destroy(record->queue);
} }
if (NULL != record->queue_buff) { if (NULL != record->queue_buff) {
free(record->queue_buff); free(record->queue_buff);
} }
if (NULL != record->buffer) { if (NULL != record->buffer) {
free(record->buffer); free(record->buffer);
} }
free(record); free(record);
} }
printf("\nrecord_stop out\n"); printf("\nrecord_stop out\n");
@ -269,6 +700,119 @@ void _record_stop(void *record_hd) {
void Netease_record_stop(struct pcm_config *config) { void Netease_record_stop(struct pcm_config *config) {
if (config != NULL && config->recordata != NULL) { if (config != NULL && config->recordata != NULL) {
_record_stop(config->recordata); config->recordata->runing = 0;
} }
} }
void device_list(void) {
snd_ctl_t *handle;
int card, err, dev, idx;
snd_ctl_card_info_t *info;
snd_pcm_info_t *pcminfo;
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
snd_ctl_card_info_alloca(&info);
snd_pcm_info_alloca(&pcminfo);
card = -1;
if (snd_card_next(&card) < 0 || card < 0) {
n_error("no soundcards found...");
return;
}
printf("**** List of %s Hardware Devices ****\n",
snd_pcm_stream_name(stream));
while (card >= 0) {
char name[32];
sprintf(name, "hw:%d", card);
if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
n_error("control open (%i): %s", card, snd_strerror(err));
goto next_card;
}
if ((err = snd_ctl_card_info(handle, info)) < 0) {
n_error("control hardware info (%i): %s", card, snd_strerror(err));
snd_ctl_close(handle);
goto next_card;
}
dev = -1;
while (1) {
unsigned int count;
if (snd_ctl_pcm_next_device(handle, &dev) < 0)
n_error("snd_ctl_pcm_next_device");
if (dev < 0)
break;
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, stream);
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
if (err != -ENOENT)
n_error("control digital audio info (%i): %s", card,
snd_strerror(err));
continue;
}
printf(("card %i: %s [%s], device %i: %s [%s]\n"), card,
snd_ctl_card_info_get_id(info),
snd_ctl_card_info_get_name(info), dev,
snd_pcm_info_get_id(pcminfo),
snd_pcm_info_get_name(pcminfo));
count = snd_pcm_info_get_subdevices_count(pcminfo);
printf((" Subdevices: %i/%i\n"),
snd_pcm_info_get_subdevices_avail(pcminfo), count);
for (idx = 0; idx < (int)count; idx++) {
snd_pcm_info_set_subdevice(pcminfo, idx);
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
n_error("control digital audio playback info (%i): %s",
card, snd_strerror(err));
} else {
printf((" Subdevice #%i: %s\n"), idx,
snd_pcm_info_get_subdevice_name(pcminfo));
}
}
}
snd_ctl_close(handle);
next_card:
if (snd_card_next(&card) < 0) {
n_error("snd_card_next");
break;
}
}
}
void pcm_list(void) {
void **hints, **n;
char *name, *descr, *descr1, *io;
const char *filter;
if (snd_device_name_hint(-1, "pcm", &hints) < 0)
return;
n = hints;
// filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
filter = "Input";
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if (io != NULL && strcmp(io, filter) != 0)
goto __end;
printf("%s\n", name);
if ((descr1 = descr) != NULL) {
printf(" ");
while (*descr1) {
if (*descr1 == '\n')
printf("\n ");
else
putchar(*descr1);
descr1++;
}
putchar('\n');
}
__end:
if (name != NULL)
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
n++;
}
snd_device_name_free_hint(hints);
}

View File

@ -1248,8 +1248,8 @@ snddmic_used = 1
;-------------------------------------------------------------------------------- ;--------------------------------------------------------------------------------
[snddaudio0] [snddaudio0]
snddaudio0_used = 1 snddaudio0_used = 1
sunxi,snddaudio-codec = sunxi,snddaudio-codec = "es7243.0-0013"
sunxi,snddaudio-codec-dai = sunxi,snddaudio-codec-dai = "es7243"
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
[daudio0] [daudio0]

View File

@ -53,7 +53,7 @@ size = 512
[partition] [partition]
name = rootfs name = rootfs
size = 65536 size = 131072
downloadfile = "rootfs.fex" downloadfile = "rootfs.fex"
user_type = 0x8000 user_type = 0x8000

View File

@ -157,7 +157,7 @@ CONFIG_KERNEL_PRINTK_TIME=y
# #
# Package build options # Package build options
# #
# CONFIG_DEBUG is not set CONFIG_DEBUG=y
# CONFIG_IPV6 is not set # CONFIG_IPV6 is not set
CONFIG_PKG_BUILD_PARALLEL=y CONFIG_PKG_BUILD_PARALLEL=y
CONFIG_PKG_BUILD_USE_JOBSERVER=y CONFIG_PKG_BUILD_USE_JOBSERVER=y
@ -165,9 +165,9 @@ CONFIG_PKG_BUILD_USE_JOBSERVER=y
# #
# Stripping options # Stripping options
# #
# CONFIG_NO_STRIP is not set CONFIG_NO_STRIP=y
# CONFIG_USE_STRIP is not set # CONFIG_USE_STRIP is not set
CONFIG_USE_SSTRIP=y # CONFIG_USE_SSTRIP is not set
# CONFIG_STRIP_KERNEL_EXPORTS is not set # CONFIG_STRIP_KERNEL_EXPORTS is not set
# CONFIG_USE_MKLIBS is not set # CONFIG_USE_MKLIBS is not set
# CONFIG_USE_UCLIBCXX is not set # CONFIG_USE_UCLIBCXX is not set
@ -2626,25 +2626,25 @@ CONFIG_PACKAGE_zlib=y
# #
# Translations # Translations
# #
# CONFIG_LUCI_LANG_uk is not set
# CONFIG_LUCI_LANG_hu is not set # CONFIG_LUCI_LANG_hu is not set
# CONFIG_LUCI_LANG_pt is not set # CONFIG_LUCI_LANG_pt is not set
# CONFIG_LUCI_LANG_sk is not set # CONFIG_LUCI_LANG_ro is not set
# CONFIG_LUCI_LANG_no is not set
# CONFIG_LUCI_LANG_en is not set # CONFIG_LUCI_LANG_en is not set
# CONFIG_LUCI_LANG_pl is not set # CONFIG_LUCI_LANG_el is not set
# CONFIG_LUCI_LANG_uk is not set # CONFIG_LUCI_LANG_sk is not set
# CONFIG_LUCI_LANG_ru is not set # CONFIG_LUCI_LANG_ja is not set
# CONFIG_LUCI_LANG_vi is not set # CONFIG_LUCI_LANG_vi is not set
# CONFIG_LUCI_LANG_he is not set # CONFIG_LUCI_LANG_he is not set
# CONFIG_LUCI_LANG_ro is not set # CONFIG_LUCI_LANG_no is not set
# CONFIG_LUCI_LANG_ms is not set # CONFIG_LUCI_LANG_ms is not set
# CONFIG_LUCI_LANG_pl is not set
# CONFIG_LUCI_LANG_zh-cn is not set # CONFIG_LUCI_LANG_zh-cn is not set
# CONFIG_LUCI_LANG_de is not set # CONFIG_LUCI_LANG_de is not set
# CONFIG_LUCI_LANG_zh-tw is not set # CONFIG_LUCI_LANG_zh-tw is not set
# CONFIG_LUCI_LANG_tr is not set # CONFIG_LUCI_LANG_tr is not set
# CONFIG_LUCI_LANG_sv is not set # CONFIG_LUCI_LANG_sv is not set
# CONFIG_LUCI_LANG_ja is not set # CONFIG_LUCI_LANG_ru is not set
# CONFIG_LUCI_LANG_el is not set
# CONFIG_LUCI_LANG_ca is not set # CONFIG_LUCI_LANG_ca is not set
# CONFIG_LUCI_LANG_es is not set # CONFIG_LUCI_LANG_es is not set
# CONFIG_LUCI_LANG_pt-br is not set # CONFIG_LUCI_LANG_pt-br is not set
@ -2837,7 +2837,7 @@ CONFIG_PACKAGE_libuvdbus=y
CONFIG_RES_NORMAL_MODE=y CONFIG_RES_NORMAL_MODE=y
# CONFIG_PACKAGE_log_ctrl is not set # CONFIG_PACKAGE_log_ctrl is not set
# CONFIG_PACKAGE_mcu_ota is not set # CONFIG_PACKAGE_mcu_ota is not set
# CONFIG_PACKAGE_netease_control_center is not set CONFIG_PACKAGE_netease_control_center=y
# CONFIG_PACKAGE_netease_test is not set # CONFIG_PACKAGE_netease_test is not set
CONFIG_PACKAGE_netease_voice=y CONFIG_PACKAGE_netease_voice=y