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
|
||||
dtb-$(CONFIG_ARCH_SUN8IW15P1) += \
|
||||
sun8iw15p1-soc.dtb \
|
||||
sun8iw15p1-mandolin-perf1.dtb\
|
||||
sun8iw15p1-mandolin-pv1.dtb
|
||||
sun8iw15p1-mandolin-perf1.dtb
|
||||
dtb-$(CONFIG_ARCH_TANGO) += \
|
||||
tango4-vantage-1172.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \
|
||||
|
|
|
@ -10,20 +10,9 @@
|
|||
|
||||
/{
|
||||
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{
|
||||
sunxi,snddaudio-codec = "ad82584f.0-0031";
|
||||
sunxi,snddaudio-codec-dai = "ad82584f";
|
||||
sunxi,snddaudio-codec = "netease1.mic.codec";
|
||||
sunxi,snddaudio-codec-dai = "netease1.mic.codecdai";
|
||||
};
|
||||
|
||||
wlan:wlan {
|
||||
|
|
|
@ -10,20 +10,9 @@
|
|||
|
||||
/{
|
||||
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{
|
||||
sunxi,snddaudio-codec = "ad82584f.0-0031";
|
||||
sunxi,snddaudio-codec-dai = "ad82584f";
|
||||
sunxi,snddaudio-codec = "netease1.mic.codec";
|
||||
sunxi,snddaudio-codec-dai = "netease1.mic.codecdai";
|
||||
};
|
||||
|
||||
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"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_ES7243
|
||||
tristate "SND_SOC_ES7243"
|
||||
depends on I2C
|
||||
|
||||
endmenu
|
||||
|
||||
# Wolfgang add ACX00
|
||||
|
|
|
@ -446,3 +446,4 @@ obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
|
|||
# Wolfgang add ACX00
|
||||
obj-$(CONFIG_SND_SOC_ACX00) += snd-soc-acx00.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 Support TDM on PCM and I2S
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.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))
|
||||
continue;
|
||||
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))
|
||||
continue;
|
||||
|
||||
|
@ -3407,6 +3409,8 @@ int snd_soc_register_codec(struct device *dev,
|
|||
|
||||
dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",
|
||||
codec->component.name);
|
||||
printk("ASoC: Registered codec '%s'\n",
|
||||
codec->component.name);
|
||||
return 0;
|
||||
|
||||
err_cleanup:
|
||||
|
|
|
@ -834,6 +834,7 @@ static int sunxi_daudio_set_clkdiv(struct snd_soc_dai *dai, int clk_id,
|
|||
else
|
||||
/* PCM mode */
|
||||
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) {
|
||||
case 1:
|
||||
|
|
|
@ -90,15 +90,15 @@ define Package/$(PKG_NAME)/install
|
|||
$(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)/nembd/evdev/bin/netease_keytest $(1)/usr/sbin/
|
||||
$(INSTALL_BIN) ./netease.init $(1)/etc/init.d/netease_services
|
||||
$(INSTALL_BIN) ./neteasewifi.init $(1)/etc/init.d/netease_wifi_service
|
||||
# $(INSTALL_BIN) ./netease.init $(1)/etc/init.d/netease_services
|
||||
# $(INSTALL_BIN) ./neteasewifi.init $(1)/etc/init.d/netease_wifi_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) ./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_rf.init $(1)/etc/init.d/netease_rf_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_rf.init $(1)/etc/init.d/netease_rf_manufacture_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) vol_adc.config $(1)/usr/share/golang/
|
||||
# $(INSTALL_DATA) ./ca-certificates.crt $(1)/etc/ssl/certs/
|
||||
|
|
|
@ -57,10 +57,18 @@ static int voice_major;
|
|||
static int voice_status;
|
||||
static double voice_confidence;
|
||||
static VoiceSessionStatus vss = VoiceSession_Init;
|
||||
static WorkMode wm = WorkMode_R311_PV1;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Function Definitions
|
||||
** ------------------------------------------------------------------------ */
|
||||
void setWorkMode(WorkMode mode) {
|
||||
wm = mode;
|
||||
}
|
||||
|
||||
WorkMode getWorkMode() {
|
||||
return wm;
|
||||
}
|
||||
void setVss(VoiceSessionStatus st) { vss = st; }
|
||||
VoiceSessionStatus getVss() { return vss; }
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ int queue_write(audio_queue_t *queue, char data[], int dataLen) {
|
|||
pthread_mutex_lock(&(queue->mutex));
|
||||
if (queue_left_asyn(queue) < dataLen) {
|
||||
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");
|
||||
//return false;
|
||||
queue_reset(queue);
|
||||
|
@ -153,13 +153,13 @@ int queue_read(audio_queue_t *queue, char **data) {
|
|||
if (queue == NULL || data == NULL) {
|
||||
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);
|
||||
pthread_mutex_lock(&(queue->mutex));
|
||||
queueBase = (char *)(queue + 1);
|
||||
begin = &((queueBase)[queue->front]);
|
||||
queueLen = queue_len_asyn(queue);
|
||||
// printf("queue_read queueLen %d\n", queueLen);
|
||||
//printf("queue_read queueLen %d\n", queueLen);
|
||||
|
||||
temp_buff = (char *)malloc(queueLen);
|
||||
if (NULL == temp_buff) {
|
||||
|
|
|
@ -26,6 +26,12 @@ extern "C" {
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Defines
|
||||
** ------------------------------------------------------------------------ */
|
||||
|
||||
#define BOARD_DMIC
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Types
|
||||
** ------------------------------------------------------------------------ */
|
||||
|
@ -51,6 +57,10 @@ typedef enum {
|
|||
VoiceSession_Created = 2
|
||||
} VoiceSessionStatus;
|
||||
|
||||
typedef enum {
|
||||
WorkMode_R311_PV1 = 0
|
||||
} WorkMode;
|
||||
|
||||
void setVss(VoiceSessionStatus st);
|
||||
VoiceSessionStatus getVss();
|
||||
|
||||
|
@ -86,6 +96,9 @@ void setVoiceConfidence(double voiceConfidence);
|
|||
double getVoiceConfidence();
|
||||
|
||||
void resetAdc();
|
||||
void setWorkMode(WorkMode mode);
|
||||
WorkMode getWorkMode();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* C++ */
|
||||
|
|
|
@ -46,7 +46,7 @@ enum {
|
|||
#endif
|
||||
|
||||
#ifdef NETEASE_DEBUG
|
||||
#define n_debug(fmt, arg...) printf(fmt, ##arg)
|
||||
#define n_debug(fmt, arg...) do{printf(fmt, ##arg);}while(0)
|
||||
#else
|
||||
#define n_debug(fmt, arg...) \
|
||||
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
|
||||
** ------------------------------------------------------------------------ */
|
||||
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);
|
||||
|
||||
|
||||
|
@ -39,13 +40,29 @@ typedef struct _RecordData{
|
|||
audio_queue_t *queue;
|
||||
char *queue_buff;
|
||||
char *buffer;
|
||||
int buff_size;
|
||||
snd_pcm_uframes_t frames;
|
||||
record_audio_fn cb;
|
||||
void *user_data;
|
||||
pthread_t tid_pcm_read;
|
||||
pthread_t tid_queue_read;
|
||||
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;
|
||||
|
||||
struct pcm_config {
|
||||
|
@ -56,11 +73,17 @@ struct pcm_config {
|
|||
unsigned int period_count;
|
||||
record_audio_fn audio_cb;
|
||||
RecordData *recordata;
|
||||
RecordData *adc;
|
||||
char *format;
|
||||
char *backupfilename;
|
||||
char *finalfilename;
|
||||
int backupfile_waveformat;
|
||||
};
|
||||
|
||||
int Neteasae_record_start(struct pcm_config *pcm_cfg);
|
||||
void Netease_record_stop(struct pcm_config *pcm_cfg);
|
||||
|
||||
void device_list(void);
|
||||
void pcm_list(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -29,10 +29,12 @@ when who why
|
|||
#include "srcwsapi.h"
|
||||
#include "uvdbus/smart_sound.h"
|
||||
#include "yunxin.h"
|
||||
#include <getopt.h>
|
||||
#include <jansson.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <uvdbus/fifo.h>
|
||||
#include <uvdbus/log.h>
|
||||
|
||||
|
@ -46,20 +48,10 @@ when who why
|
|||
/* ------------------------------------------------------------------------
|
||||
** Macros
|
||||
** ------------------------------------------------------------------------ */
|
||||
#define BACKUP_ORIG_AUDIO
|
||||
//#define BACKUP_FINAL_AUDIO
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** 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
|
||||
|
||||
|
@ -73,7 +65,8 @@ static int fd_audio_final;
|
|||
** Global Variable Definitions
|
||||
** ------------------------------------------------------------------------ */
|
||||
// unsigned int g_bIsUsedTestServer;
|
||||
|
||||
static int in_aborting = 0;
|
||||
static int justrecord = 0;
|
||||
/* ------------------------------------------------------------------------
|
||||
** Functions
|
||||
** ------------------------------------------------------------------------ */
|
||||
|
@ -87,10 +80,26 @@ const char *g_fmaeCfgPath = "/usr/share/fmae_res/config.ini";
|
|||
CAEDATA *caeconfig = NULL;
|
||||
#endif
|
||||
|
||||
struct pcm_config recordconfig;
|
||||
struct pcm_config recordconfig = {0};
|
||||
struct audio_bypass *audiobypassconfig = NULL;
|
||||
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
|
||||
static struct kfifo g_AudioCacheBuf;
|
||||
// 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 fd;
|
||||
size_t hasWritten;
|
||||
|
||||
if (type == DUILITE_MSG_TYPE_BINARY) {
|
||||
// n_debug("Get beforming binary data:%d\n", len);
|
||||
#ifdef BACKUP_FINAL_AUDIO
|
||||
write(fd_audio_final, msg, len);
|
||||
#endif
|
||||
if (recordconfig.recordata && recordconfig.recordata->finalfilefd > 0) {
|
||||
write(recordconfig.recordata->finalfilefd, msg, len);
|
||||
}
|
||||
if (!!audiobypassconfig) {
|
||||
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,
|
||||
int err_code) {
|
||||
unsigned long long cachetime;
|
||||
|
||||
#ifdef DEBUG_WASTE_TIME
|
||||
Netease_caltime(&cachetime, 1);
|
||||
#endif
|
||||
|
@ -280,11 +292,6 @@ static void record_audio_cb(const void *audio, unsigned int audio_len,
|
|||
int ret = 0;
|
||||
#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 (1) {
|
||||
#elif USED_NETEASE_DUILITE
|
||||
|
@ -499,23 +506,153 @@ void LogFunc(int logLevel, const char *log, void *userData) {
|
|||
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) {
|
||||
int ret;
|
||||
unsigned int card = 1;
|
||||
unsigned int device = 0;
|
||||
unsigned int channels = 2;
|
||||
unsigned int rate = 96000;
|
||||
int ret, c, option_index, err,tmp;
|
||||
char *rawfile = "/dev/null";
|
||||
char *finalfile = "/dev/null";
|
||||
static const char short_options[] = "hlt:w:Lfr";
|
||||
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;
|
||||
unsigned int period_size = 1535;
|
||||
unsigned int period_count = 4;
|
||||
recordconfig.backupfile_waveformat = 1;
|
||||
recordconfig.audio_cb = record_audio_cb;
|
||||
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
|
||||
ret = Netease_dbus_oem_init(DBusMessageCb);
|
||||
#else
|
||||
// ret = Netease_Dbus_Init(DBusMessageCb);
|
||||
ret = Netease_Dbus_Init(DBusMessageCb);
|
||||
#endif
|
||||
if (NETEASE_SUCCESS == ret) {
|
||||
n_debug("Dbus init success\n");
|
||||
|
@ -546,42 +683,6 @@ void main(int argc, char **argv) {
|
|||
}
|
||||
#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
|
||||
ret = Netease_audiobypass_init(&audiobypassconfig, NULL,
|
||||
AUDIO_BYPASS_CHANNEL_MSC_IAT);
|
||||
|
@ -666,10 +767,27 @@ void main(int argc, char **argv) {
|
|||
#ifdef ENABLE_OEM_DBUS
|
||||
pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL);
|
||||
#else
|
||||
// pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
|
||||
pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
|
||||
#endif
|
||||
// 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) {
|
||||
if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) {
|
||||
// n_toast("Get args frome cc\n");
|
||||
|
|
|
@ -352,6 +352,29 @@ int Netease_nduilite_init(duilite_callback wakeup_callback,
|
|||
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,
|
||||
unsigned int audio_len) {
|
||||
int len = 0;
|
||||
|
@ -372,6 +395,10 @@ void Netease_nduilite_writeaudio(const void *audioData,
|
|||
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);
|
||||
|
||||
if (newbuf == NULL) {
|
||||
|
@ -388,4 +415,5 @@ void Netease_nduilite_writeaudio(const void *audioData,
|
|||
write(fd_audio_orig, newbuf, len);
|
||||
#endif
|
||||
free(newbuf);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ when who why
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "formats.h"
|
||||
#include "record.h"
|
||||
|
||||
#include "error.h"
|
||||
|
@ -35,6 +37,7 @@ when who why
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Macros
|
||||
|
@ -42,7 +45,7 @@ when who why
|
|||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||
#define AUDIO_QUEUE_BUFF_LEN (1024 * 10)
|
||||
|
||||
#define QUEUE_BUFF_MULTIPLE 1000
|
||||
#define QUEUE_BUFF_MULTIPLE 100
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Types
|
||||
|
@ -64,14 +67,40 @@ static Proc_CAEGetChannel api_cae_get_channel;
|
|||
static Proc_CAESetShowLog api_cae_set_show_log;
|
||||
static Proc_CAEDestroy api_cae_destroy;
|
||||
|
||||
static off64_t fdcount = 0;
|
||||
static snd_output_t *sndlog;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Function Definitions
|
||||
** ------------------------------------------------------------------------ */
|
||||
static void *QueueReadThread(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,
|
||||
int err_code);
|
||||
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) {
|
||||
RecordData *record = (RecordData *)param;
|
||||
|
@ -83,7 +112,7 @@ static void *QueueReadThread(void *param) {
|
|||
if (0 == readLen) {
|
||||
// printf("queue_read readLen = 0\n");
|
||||
// usleep(16000);
|
||||
// continue;
|
||||
continue;
|
||||
}
|
||||
if (record->buff_size != readLen) {
|
||||
// printf("\nqueue_read readLen %d\n", readLen);
|
||||
|
@ -96,57 +125,380 @@ static void *QueueReadThread(void *param) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *RecordThread(void *param) {
|
||||
RecordData *record = (RecordData *)param;
|
||||
int ret = 0;
|
||||
// cpu_set_t mask;
|
||||
n_toast("RecordThread record:%p, running:%d\n", record, record->runing);
|
||||
// CPU_ZERO(&mask);
|
||||
// CPU_SET(0,&mask);
|
||||
// ret = sched_setaffinity(0, sizeof(mask), &mask);
|
||||
// printf("sched_setaffinity return = %d\n", ret);
|
||||
while (!!record->runing) {
|
||||
ret = snd_pcm_readi(record->handle, record->buffer, record->frames);
|
||||
// printf("snd_pcm_readi return = %d\n", ret);
|
||||
if (ret == -EPIPE) {
|
||||
static void do_test_position(RecordData *record) {
|
||||
static long counter = 0;
|
||||
static time_t tmr = -1;
|
||||
time_t now;
|
||||
static float availsum, delaysum, samples;
|
||||
static snd_pcm_sframes_t maxavail, maxdelay;
|
||||
static snd_pcm_sframes_t minavail, mindelay;
|
||||
static snd_pcm_sframes_t badavail = 0, baddelay = 0;
|
||||
snd_pcm_sframes_t outofrange;
|
||||
snd_pcm_sframes_t avail, delay;
|
||||
int err;
|
||||
int test_coef = 8;
|
||||
|
||||
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 */
|
||||
fprintf(stderr, "overrun occurred/n");
|
||||
LOG_EX(LOG_Error, "ALSA Read Data = -EPIPE\n");
|
||||
snd_pcm_prepare(record->handle);
|
||||
continue;
|
||||
} else if (ret < 0) {
|
||||
fprintf(stderr, "error from read: %s/n", snd_strerror(ret));
|
||||
LOG_EX(LOG_Error, "ALSA Read Data Error: %s(%d)\n", snd_strerror(ret), ret);
|
||||
record->cb(NULL, 0, ret);
|
||||
return NULL;
|
||||
} 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);
|
||||
} else if (r < 0) {
|
||||
fprintf(stderr, "error from read: %s/n", snd_strerror(r));
|
||||
LOG_EX(LOG_Error, "ALSA Read Data Error: %s(%d)\n", snd_strerror(r),
|
||||
r);
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
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) {
|
||||
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 size;
|
||||
int ret = NETEASE_SUCCESS;
|
||||
pthread_attr_t thread_attr;
|
||||
struct sched_param thread_param;
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
unsigned int val, val2;
|
||||
int dir;
|
||||
snd_pcm_uframes_t frames;
|
||||
char *buffer;
|
||||
struct stat statbuf;
|
||||
|
||||
RecordData *record = (RecordData *)malloc(sizeof(RecordData));
|
||||
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));
|
||||
|
||||
pcm_cfg->recordata = record;
|
||||
record->pcm_cfg = pcm_cfg;
|
||||
record->cb = pcm_cfg->audio_cb;
|
||||
|
||||
//设置录音参数参数
|
||||
|
@ -157,8 +509,21 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
|||
ret = NETEASE_ERROR_OPEN_FILE;
|
||||
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. */
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
/* Fill it in with default values. */
|
||||
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);
|
||||
|
||||
/* 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) */
|
||||
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) */
|
||||
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. */
|
||||
frames = pcm_cfg->period_size;
|
||||
snd_pcm_hw_params_set_period_size_near(record->handle, params, &frames,
|
||||
&dir);
|
||||
record->frames = frames;
|
||||
// frames = pcm_cfg->period_size;
|
||||
// snd_pcm_hw_params_set_period_size_near(record->handle, params, &frames,
|
||||
// 0);
|
||||
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 */
|
||||
rc = snd_pcm_hw_params(record->handle, params);
|
||||
if (rc < 0) {
|
||||
n_error("unable to set hw parameters: %s/n", snd_strerror(rc));
|
||||
// snd_pcm_hw_dump(params, sndlog);
|
||||
ret = NETEASE_ERROR_FAIL;
|
||||
goto error;
|
||||
}
|
||||
// snd_pcm_hw_params_dump(params, stdout);
|
||||
snd_pcm_dump(record->handle, sndlog);
|
||||
/* Use a buffer large enough to hold one period */
|
||||
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
|
||||
size = frames * 8; /* 4 bytes/sample, 2 channels */
|
||||
record->buff_size = size;
|
||||
n_toast("frames=%ld,record->buff_size=%d\n", frames, record->buff_size);
|
||||
record->buffer = (char *)malloc(size);
|
||||
record->bits_per_sample = snd_pcm_format_physical_width(record->format);
|
||||
record->significant_bits_per_sample = snd_pcm_format_width(record->format);
|
||||
record->bits_per_frame = record->bits_per_sample * pcm_cfg->channels;
|
||||
record->chunk_bytes = record->chunk_size * record->bits_per_frame / 8;
|
||||
|
||||
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) {
|
||||
ret = NETEASE_ERROR_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
record->queue_buff =
|
||||
(char *)malloc(sizeof(audio_queue_t) + size * QUEUE_BUFF_MULTIPLE + 1);
|
||||
if (NULL == record->queue_buff) {
|
||||
ret = NETEASE_ERROR_OUT_OF_MEMORY;
|
||||
if (init_queue > 0) {
|
||||
record->queue_buff = (char *)malloc(
|
||||
sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
pthread_create(&record->tid_pcm_read, &thread_attr, RecordThread,
|
||||
(void *)record);
|
||||
pthread_create(&record->tid_queue_read, NULL, QueueReadThread,
|
||||
(void *)record);
|
||||
|
||||
goto exit;
|
||||
|
||||
|
@ -239,13 +671,12 @@ void _record_stop(void *record_hd) {
|
|||
printf("\nrecord_stop in record:%p\n\n", record);
|
||||
if (NULL != record) {
|
||||
record->runing = 0;
|
||||
if(NULL != record->tid_pcm_read)
|
||||
if (NULL != record->tid_pcm_read)
|
||||
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);
|
||||
|
||||
if(NULL != record->handle)
|
||||
{
|
||||
if (NULL != record->handle) {
|
||||
snd_pcm_drain(record->handle);
|
||||
snd_pcm_close(record->handle);
|
||||
}
|
||||
|
@ -269,6 +700,119 @@ void _record_stop(void *record_hd) {
|
|||
|
||||
void Netease_record_stop(struct pcm_config *config) {
|
||||
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_used = 1
|
||||
sunxi,snddaudio-codec =
|
||||
sunxi,snddaudio-codec-dai =
|
||||
sunxi,snddaudio-codec = "es7243.0-0013"
|
||||
sunxi,snddaudio-codec-dai = "es7243"
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
[daudio0]
|
||||
|
|
|
@ -53,7 +53,7 @@ size = 512
|
|||
|
||||
[partition]
|
||||
name = rootfs
|
||||
size = 65536
|
||||
size = 131072
|
||||
downloadfile = "rootfs.fex"
|
||||
user_type = 0x8000
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ CONFIG_KERNEL_PRINTK_TIME=y
|
|||
#
|
||||
# Package build options
|
||||
#
|
||||
# CONFIG_DEBUG is not set
|
||||
CONFIG_DEBUG=y
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_PKG_BUILD_PARALLEL=y
|
||||
CONFIG_PKG_BUILD_USE_JOBSERVER=y
|
||||
|
@ -165,9 +165,9 @@ CONFIG_PKG_BUILD_USE_JOBSERVER=y
|
|||
#
|
||||
# Stripping options
|
||||
#
|
||||
# CONFIG_NO_STRIP is not set
|
||||
CONFIG_NO_STRIP=y
|
||||
# CONFIG_USE_STRIP is not set
|
||||
CONFIG_USE_SSTRIP=y
|
||||
# CONFIG_USE_SSTRIP is not set
|
||||
# CONFIG_STRIP_KERNEL_EXPORTS is not set
|
||||
# CONFIG_USE_MKLIBS is not set
|
||||
# CONFIG_USE_UCLIBCXX is not set
|
||||
|
@ -2626,25 +2626,25 @@ CONFIG_PACKAGE_zlib=y
|
|||
#
|
||||
# Translations
|
||||
#
|
||||
# CONFIG_LUCI_LANG_uk is not set
|
||||
# CONFIG_LUCI_LANG_hu is not set
|
||||
# CONFIG_LUCI_LANG_pt is not set
|
||||
# CONFIG_LUCI_LANG_sk is not set
|
||||
# CONFIG_LUCI_LANG_no is not set
|
||||
# CONFIG_LUCI_LANG_ro is not set
|
||||
# CONFIG_LUCI_LANG_en is not set
|
||||
# CONFIG_LUCI_LANG_pl is not set
|
||||
# CONFIG_LUCI_LANG_uk is not set
|
||||
# CONFIG_LUCI_LANG_ru is not set
|
||||
# CONFIG_LUCI_LANG_el is not set
|
||||
# CONFIG_LUCI_LANG_sk is not set
|
||||
# CONFIG_LUCI_LANG_ja is not set
|
||||
# CONFIG_LUCI_LANG_vi 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_pl is not set
|
||||
# CONFIG_LUCI_LANG_zh-cn is not set
|
||||
# CONFIG_LUCI_LANG_de is not set
|
||||
# CONFIG_LUCI_LANG_zh-tw is not set
|
||||
# CONFIG_LUCI_LANG_tr is not set
|
||||
# CONFIG_LUCI_LANG_sv is not set
|
||||
# CONFIG_LUCI_LANG_ja is not set
|
||||
# CONFIG_LUCI_LANG_el is not set
|
||||
# CONFIG_LUCI_LANG_ru is not set
|
||||
# CONFIG_LUCI_LANG_ca is not set
|
||||
# CONFIG_LUCI_LANG_es 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_PACKAGE_log_ctrl 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_voice=y
|
||||
|
||||
|
|
Loading…
Reference in New Issue