Merge branch 'master' of ssh://g.hz.netease.com:22222/IoT/PV2/SmartAudioPV2
This commit is contained in:
commit
ad4d7723a0
Binary file not shown.
|
@ -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) += \
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
|
@ -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
|
@ -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
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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/
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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++ */
|
||||||
|
|
|
@ -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 { \
|
||||||
|
|
|
@ -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 */
|
|
@ -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" */
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¶ms);
|
snd_pcm_hw_params_alloca(¶ms);
|
||||||
|
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);
|
||||||
|
}
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue