add es7243 adc driver, add new codec linked with i2s0, rewrite audio capture code in netease voice, add dmic support, add adc input support, add data convert for duilite
This commit is contained in:
parent
7550320002
commit
42986a822f
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/
|
||||
|
|
|
@ -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
|
||||
** ------------------------------------------------------------------------ */
|
||||
|
|
|
@ -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,28 @@ 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;
|
||||
struct pcm_config *pcm_cfg;
|
||||
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;
|
||||
|
||||
snd_output_t *log;
|
||||
}RecordData;
|
||||
|
||||
struct pcm_config {
|
||||
|
@ -56,6 +72,9 @@ struct pcm_config {
|
|||
unsigned int period_count;
|
||||
record_audio_fn audio_cb;
|
||||
RecordData *recordata;
|
||||
char *format;
|
||||
char *backupfilename;
|
||||
int backupfile_waveformat;
|
||||
};
|
||||
|
||||
int Neteasae_record_start(struct pcm_config *pcm_cfg);
|
||||
|
|
|
@ -46,8 +46,8 @@ when who why
|
|||
/* ------------------------------------------------------------------------
|
||||
** Macros
|
||||
** ------------------------------------------------------------------------ */
|
||||
#define BACKUP_ORIG_AUDIO
|
||||
//#define BACKUP_FINAL_AUDIO
|
||||
//#define BACKUP_ORIG_AUDIO
|
||||
#define BACKUP_FINAL_AUDIO
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Defines
|
||||
|
@ -55,6 +55,7 @@ when who why
|
|||
#ifdef BACKUP_ORIG_AUDIO
|
||||
#define ORIG_AUDIO_FILENAME "/mnt/UDISK/origaudio.pcm"
|
||||
static int fd_audio_orig;
|
||||
char *BACKUP_PATH;
|
||||
#endif
|
||||
|
||||
#ifdef BACKUP_FINAL_AUDIO
|
||||
|
@ -73,7 +74,7 @@ static int fd_audio_final;
|
|||
** Global Variable Definitions
|
||||
** ------------------------------------------------------------------------ */
|
||||
// unsigned int g_bIsUsedTestServer;
|
||||
|
||||
static int in_aborting = 0;
|
||||
/* ------------------------------------------------------------------------
|
||||
** Functions
|
||||
** ------------------------------------------------------------------------ */
|
||||
|
@ -221,10 +222,20 @@ 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);
|
||||
fd = open("/tmp/finalaudio", O_CREAT | O_APPEND | O_RDWR);
|
||||
if (fd > 0) {
|
||||
hasWritten = write(fd, msg, len);
|
||||
close(fd);
|
||||
|
||||
n_debug("Has written:%d\n", hasWritten);
|
||||
} else {
|
||||
n_error("open file(%s) error: %d", "/tmp/finalaudio", fd);
|
||||
}
|
||||
#endif
|
||||
if (!!audiobypassconfig) {
|
||||
Netease_audiobypass_write(audiobypassconfig, msg, len);
|
||||
|
@ -272,6 +283,10 @@ 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 BACKUP_ORIG_AUDIO
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WASTE_TIME
|
||||
Netease_caltime(&cachetime, 1);
|
||||
#endif
|
||||
|
@ -280,11 +295,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,19 +509,42 @@ 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);
|
||||
}
|
||||
|
||||
void main(int argc, char **argv) {
|
||||
int ret;
|
||||
|
||||
#ifdef BOARD_DMIC
|
||||
unsigned int channels = 8;
|
||||
unsigned int rate = 16000;
|
||||
unsigned int card = 1;
|
||||
unsigned int device = 0;
|
||||
#else
|
||||
unsigned int card = 2;
|
||||
unsigned int device = 0;
|
||||
unsigned int channels = 2;
|
||||
unsigned int rate = 96000;
|
||||
|
||||
#endif
|
||||
// unsigned int frames;
|
||||
unsigned int period_size = 1535;
|
||||
unsigned int period_count = 4;
|
||||
|
||||
char sound_device_name[30];
|
||||
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
|
||||
#ifdef ENABLE_OEM_DBUS
|
||||
ret = Netease_dbus_oem_init(DBusMessageCb);
|
||||
#else
|
||||
|
@ -546,7 +579,7 @@ void main(int argc, char **argv) {
|
|||
}
|
||||
#endif
|
||||
|
||||
snprintf(sound_device_name, sizeof(sound_device_name), "plughw:%u,%u", card,
|
||||
snprintf(sound_device_name, sizeof(sound_device_name), "hw:%u,%u", card,
|
||||
device);
|
||||
|
||||
recordconfig.device_name = sound_device_name;
|
||||
|
@ -555,6 +588,9 @@ void main(int argc, char **argv) {
|
|||
recordconfig.period_size = period_size;
|
||||
recordconfig.period_count = period_count;
|
||||
recordconfig.audio_cb = record_audio_cb;
|
||||
recordconfig.format = "S16_LE";
|
||||
recordconfig.backupfilename = NULL;
|
||||
recordconfig.backupfile_waveformat = 0;
|
||||
// todo write something
|
||||
printf("++++++++++++++++++++++++++\n");
|
||||
printf("device name is %s\n", recordconfig.device_name);
|
||||
|
@ -564,21 +600,15 @@ void main(int argc, char **argv) {
|
|||
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);
|
||||
recordconfig.audio_cb = NULL;
|
||||
recordconfig.backupfilename = argv[1];
|
||||
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();
|
||||
|
||||
|
@ -670,6 +700,23 @@ void main(int argc, char **argv) {
|
|||
#endif
|
||||
// Netease_yunxin_test();
|
||||
|
||||
#if 1
|
||||
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,11 @@ void Netease_nduilite_writeaudio(const void *audioData,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef BOARD_DMIC
|
||||
//n_debug("Write nduilite data, len:%d\n", audio_len);
|
||||
Dmic_data_convert(audioData, audio_len);
|
||||
ret = duilite_fespa_feed(fespa, audioData, audio_len);
|
||||
#else
|
||||
newbuf = (char *)malloc(audio_len + 60);
|
||||
|
||||
if (newbuf == NULL) {
|
||||
|
@ -388,4 +416,5 @@ void Netease_nduilite_writeaudio(const void *audioData,
|
|||
write(fd_audio_orig, newbuf, len);
|
||||
#endif
|
||||
free(newbuf);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ when who why
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "formats.h"
|
||||
#include "record.h"
|
||||
|
||||
#include "error.h"
|
||||
|
@ -35,6 +36,7 @@ when who why
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Macros
|
||||
|
@ -42,7 +44,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 500
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** Types
|
||||
|
@ -64,14 +66,38 @@ 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;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
** 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);
|
||||
|
||||
/*
|
||||
* 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 +109,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,39 +122,242 @@ static void *QueueReadThread(void *param) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
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 (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;
|
||||
}
|
||||
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;
|
||||
long long max_file_size = 2147483648LL;
|
||||
|
||||
// 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);
|
||||
if (record->backupfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
|
||||
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
|
||||
fdcount = 0;
|
||||
}
|
||||
while (!!record->runing) {
|
||||
ret = snd_pcm_readi(record->handle, record->buffer, record->frames);
|
||||
// printf("snd_pcm_readi return = %d\n", ret);
|
||||
if (ret == -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) {
|
||||
if (pcm_read(record) == record->chunk_size) {
|
||||
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);
|
||||
}
|
||||
queue_write(record->queue, record->buffer, record->buff_size);
|
||||
}
|
||||
|
||||
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) {
|
||||
int rc;
|
||||
int size;
|
||||
|
@ -136,18 +365,23 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
|||
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;
|
||||
}
|
||||
pcm_cfg->recordata = record;
|
||||
memset(record, 0, sizeof(RecordData));
|
||||
|
||||
pcm_cfg->recordata = record;
|
||||
record->pcm_cfg = pcm_cfg;
|
||||
record->cb = pcm_cfg->audio_cb;
|
||||
snd_output_stdio_attach(&record->log, stderr, 0);
|
||||
|
||||
//设置录音参数参数
|
||||
rc = snd_pcm_open(&record->handle, pcm_cfg->device_name,
|
||||
|
@ -157,8 +391,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,47 +416,94 @@ 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, stdout);
|
||||
ret = NETEASE_ERROR_FAIL;
|
||||
goto error;
|
||||
}
|
||||
// snd_pcm_hw_params_dump(params, stdout);
|
||||
snd_pcm_dump(record->handle, record->log);
|
||||
/* 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);
|
||||
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, size * QUEUE_BUFF_MULTIPLE + 1);
|
||||
record->queue = queue_init(record->queue_buff,
|
||||
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
|
||||
|
@ -218,12 +512,22 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
|||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
||||
error:
|
||||
|
@ -239,13 +543,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 +572,6 @@ 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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -158,7 +158,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
|
||||
|
@ -166,9 +166,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
|
||||
|
@ -2627,25 +2627,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
|
||||
|
@ -2831,7 +2831,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