7 Star 2 Fork 0

yocop/drv_snd_pangu

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
pangu_drv.c 23.36 KB
一键复制 编辑 原始数据 按行查看 历史
hlb194802 提交于 2021-08-20 14:36 . update v7.4.5
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
/*
* Copyright (C) 2019-2020 Alibaba Group Holding Limited
*/
#ifdef CONFIG_CSI_V1
#include <aos/aos.h>
#include <alsa/snd.h>
#include <alsa/pcm.h>
#include <alsa/mixer.h>
#include <soc.h>
#include <drv/codec.h>
#include <devices/drv_snd_pangu.h>
#include <drv/ringbuf.h>
#define TAG "snd"
#define pcm_uninit device_free
#define mixer_uninit device_free
#define pcm_dev(dev) &(((aos_pcm_dev_t *)dev)->pcm)
#define pcm_ops(dev) &(((aos_pcm_drv_t *)((((aos_pcm_dev_t *)dev)->device.drv)))->ops)
#define DAC_WRITE_EVENT (0x01)
#define ADC_READ_EVENT (0x02)
typedef struct {
#ifdef CONFIG_CSI_V2
csi_codec_output_t *hdl;
#else
codec_output_t *hdl;
#endif
aos_pcm_hw_params_t params;
int state;
/* patch for baoyin */
int pause;
int wcnt;
int wcnt_threshold;
} playback_t;
typedef struct {
#ifdef CONFIG_CSI_V2
csi_codec_input_t *hdl;
#else
codec_input_t *hdl;
#endif
aos_pcm_hw_params_t params;
int channels;
char *recv;
int state;
} capture_t;
typedef struct {
#ifdef CONFIG_CSI_V2
csi_codec_output_t hdl;
#else
codec_output_t hdl;
#endif
int l;
int r;
int mute;
} mixer_playback_t;
static mixer_playback_t mixp0 = {{0,}, -31, -31};
static int g_dac_gain_min = -62;
static int g_dac_gain_max = -18;
static int g_snd_ref_id = -1;
#ifdef CONFIG_CSI_V2
static csi_codec_t codec_a;
static csi_ringbuf_t output_ring_buffer;
static csi_ringbuf_t input_ring_buffer;
#endif
static int snd_set_gain(aos_mixer_elem_t *elem, int l, int r);
static int pcmp_param_set(aos_pcm_t *pcm, struct aos_pcm_hw_params *params);
static int pcmc_param_set(aos_pcm_t *pcm, struct aos_pcm_hw_params *params);
static void playback_free(playback_t *playback)
{
aos_assert(playback != NULL);
if (playback->state == 1) {
csi_codec_output_stop(playback->hdl);
csi_codec_output_close(playback->hdl);
#ifdef CONFIG_CSI_V2
aos_free(playback->hdl->ring_buf);
#else
aos_free(playback->hdl->buf);
#endif
aos_free(playback->hdl);
playback->state = 0;
playback->hdl = 0;
}
}
static int pcmp_lpm(aos_dev_t *dev, int state)
{
aos_pcm_t *pcm = pcm_dev(dev);
playback_t *playback = (playback_t *)pcm->hdl;
if (playback == NULL) {
return 0;
}
if (state > 0) {
playback_free(playback);
} else {
pcmp_param_set(pcm, &playback->params);
}
return 0;
}
static int pcmp_open(aos_dev_t *dev)
{
aos_pcm_t *pcm = pcm_dev(dev);
playback_t *playback = aos_zalloc(sizeof(playback_t));
if (playback) {
pcm->hdl = playback;
playback->state = 0;
return 0;
}
return -1;
}
static int pcmp_close(aos_dev_t *dev)
{
aos_pcm_t *pcm = pcm_dev(dev);
playback_t *playback = (playback_t *)pcm->hdl;
playback_free(playback);
aos_free(playback);
pcm->hdl = NULL;
return 0;
}
#ifdef CONFIG_CSI_V2
static void codec_event_cb(csi_codec_input_t *codec, csi_codec_event_t event, void *arg)
#else
static void codec_event_cb(int idx, codec_event_t event, void *arg)
#endif
{
aos_pcm_t *pcm = (aos_pcm_t *)arg;
if (event == CODEC_EVENT_PERIOD_WRITE_COMPLETE) {
pcm->event.cb(pcm, PCM_EVT_WRITE, pcm->event.priv);
} else if (event == CODEC_EVENT_PERIOD_READ_COMPLETE) {
pcm->event.cb(pcm, PCM_EVT_READ, pcm->event.priv);
} else {
pcm->event.cb(pcm, PCM_EVT_XRUN, pcm->event.priv);
}
}
//FIXME: frequent switching of mute will cause popping
static void _csi_codec_output_mute(int mute)
{
#ifdef CONFIG_CSI_V2
csi_codec_output_t *p = &mixp0.hdl;
#else
codec_output_t *p = &mixp0.hdl;
#endif
if (p && (mute != mixp0.mute)) {
csi_codec_output_mute(p, mute);
mixp0.mute = mute;
}
}
static int pcmp_param_set(aos_pcm_t *pcm, aos_pcm_hw_params_t *params)
{
playback_t *playback = (playback_t *)pcm->hdl;
playback_free(playback);
#ifdef CONFIG_CSI_V2
csi_codec_output_config_t output_config;
csi_codec_output_t *codec = aos_zalloc(sizeof(csi_codec_output_t));
if (codec == NULL) {
return -1;
}
codec->ring_buf = &output_ring_buffer;
#else
codec_output_t *codec = aos_zalloc(sizeof(codec_output_t));
if (codec == NULL) {
return -1;
}
#endif
uint8_t *send = aos_malloc(params->buffer_bytes);
if (!(send)) {
goto pcmp_err0;
}
#ifdef CONFIG_CSI_V2
csi_codec_output_open(&codec_a, codec, 0);
csi_codec_output_attach_callback(codec, codec_event_cb, NULL);
output_config.bit_width = params->sample_bits;
output_config.sample_rate = params->rate;
output_config.buffer = send;
output_config.buffer_size = params->buffer_bytes;
output_config.period = params->period_bytes;
output_config.mode = CODEC_OUTPUT_SINGLE_ENDED;
output_config.sound_channel_num = params->channels;
int ret = csi_codec_output_config(codec, &output_config);
if (ret != 0) {
goto pcmp_err1;
}
#else
codec->buf = send;
codec->buf_size = params->buffer_bytes;
codec->cb = codec_event_cb;
codec->cb_arg = pcm;
codec->ch_idx = pcm->pcm_name[4] - 0x30;
codec->codec_idx = 0;
codec->period = params->period_bytes;
/**
*The gasket tx may occasionally be abnormal.
*This problem can be temporarily solved by
*resetting the gasket every time a song is played.
*/
int ret = csi_codec_output_open(codec);
if (ret != 0) {
goto pcmp_err1;
}
codec_output_config_t config;
config.bit_width = params->sample_bits;
config.mono_mode_en = params->channels == 1 ? 1 : 0;
config.sample_rate = params->rate;
ret = csi_codec_output_config(codec, &config);
if (ret != 0) {
goto pcmp_err1;
}
#endif
csi_codec_output_start(codec);
#ifdef CONFIG_CSI_V2
if (mixp0.hdl.callback == NULL) {
memcpy(&mixp0.hdl, codec, sizeof(csi_codec_output_t));
snd_set_gain(NULL, mixp0.l, mixp0.r);
}
#else
if (mixp0.hdl.cb == NULL) {
memcpy(&mixp0.hdl, codec, sizeof(codec_output_t));
snd_set_gain(NULL, mixp0.l, mixp0.r);
}
#endif
playback->state = 1;
playback->hdl = codec;
/* patch for baoyin */
playback->wcnt_threshold = params->rate / 1000 * params->channels * params->sample_bits / 8 * 40;
memcpy(&playback->params, params, sizeof(aos_pcm_hw_params_t));
return 0;
pcmp_err1:
aos_free(send);
pcmp_err0:
aos_free(codec);
return -1;
}
static int pcm_send(aos_pcm_t *pcm, void *data, int len)
{
playback_t *playback = (playback_t *)pcm->hdl;
int ret = csi_codec_output_write(playback->hdl, (uint8_t *)data, len);
if (ret > 0 && playback->pause) {
playback->wcnt += ret;
if (playback->wcnt >= playback->wcnt_threshold) {
playback->pause = 0;
playback->wcnt = 0;
csi_codec_output_resume(playback->hdl);
}
}
return ret;
}
static int pcm_pause(aos_pcm_t *pcm, int enable)
{
playback_t *playback = (playback_t *)pcm->hdl;
if (enable) {
playback->pause = 1;
playback->wcnt = 0;
csi_codec_output_pause(playback->hdl);
} else {
//FIXME: patch for xiaoya on mixer
//csi_codec_output_resume(playback->hdl);
#ifdef CONFIG_CSI_V2
memset(playback->hdl->ring_buf->buffer, 0, playback->hdl->ring_buf->size);
#else
memset(playback->hdl->buf, 0, playback->hdl->buf_size);
#endif
}
return 0;
}
/* left_gain/right_gain [g_dac_gain_min, g_dac_gain_max] 1dB step*/
static int snd_set_gain(aos_mixer_elem_t *elem, int l, int r)
{
#ifdef CONFIG_CSI_V2
if (mixp0.hdl.callback != NULL) {
csi_codec_output_t *p = &mixp0.hdl;
#else
if (mixp0.hdl.cb != NULL) {
codec_output_t *p = &mixp0.hdl;
#endif
int tmp_r = r;
int tmp_l = l;
/* min == max is debug mode, need set gain */
if ((tmp_l <= g_dac_gain_min || tmp_r <= g_dac_gain_min) && g_dac_gain_min != g_dac_gain_max) {
_csi_codec_output_mute(1);
} else {
_csi_codec_output_mute(0);
#ifdef CONFIG_CSI_V2
csi_codec_output_analog_gain(p, tmp_l < -31 ? -31 : tmp_l);
#else
csi_codec_output_set_analog_left_gain(p, tmp_l < -31 ? -31 : tmp_l);
csi_codec_output_set_analog_right_gain(p, tmp_r < -31 ? -31 : tmp_r);
#endif
tmp_l = tmp_l >= -31 ? 0 : tmp_l + 31;
tmp_r = tmp_r >= -31 ? 0 : tmp_r + 31;
#ifdef CONFIG_CSI_V2
csi_codec_output_mix_gain(p, tmp_l);
#else
csi_codec_output_set_mixer_left_gain(p, tmp_l);
csi_codec_output_set_mixer_right_gain(p, tmp_r);
#endif
}
}
mixp0.l = l;
mixp0.r = r;
return 0;
}
static int snd_volume_to_dB(aos_mixer_elem_t *elem, int val)
{
/* debug ignore gain from volume control */
if (g_dac_gain_max == g_dac_gain_min) {
return g_dac_gain_max;
}
int gain;
int gain_s = g_dac_gain_min, gain_e = g_dac_gain_max;
//FIXME
gain = gain_s + (val / 100.0 * (gain_e - gain_s));
if (gain >= gain_e ) {
gain = gain_e;
}
if (gain <= gain_s ) {
gain = gain_s;
}
return gain;
}
static sm_elem_ops_t elem_codec1_ops = {
.set_dB = snd_set_gain,
.volume_to_dB = snd_volume_to_dB,
};
static aos_dev_t *pcm_init(driver_t *drv, void *config, int id)
{
aos_pcm_dev_t *pcm_dev = (aos_pcm_dev_t *)device_new(drv, sizeof(aos_pcm_dev_t), id);
aos_pcm_drv_t *pcm_drv = (aos_pcm_drv_t *)drv;
memset(&pcm_dev->pcm, 0x00, sizeof(aos_pcm_t));
pcm_dev->pcm.ops = &(pcm_drv->ops);
return (aos_dev_t *)(pcm_dev);
}
static void capture_free(capture_t *capture)
{
if (capture->state == 1) {
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
#else
codec_input_t *codec = capture->hdl;
#endif
for (int i = 0; i < capture->channels; i++) {
if (codec) {
#ifdef CONFIG_CSI_V1
if (codec->ch_idx >= 0)
#endif
{
csi_codec_input_stop(codec);
csi_codec_input_close(codec);
}
codec ++;
}
}
// aos_free(capture->hdl->buf);
aos_free(capture->recv);
aos_free(capture->hdl);
capture->state = 0;
capture->hdl = 0;
}
}
extern csi_ringbuf_t *drv_codec_input_fifo_get(int32_t ch);
static int pcmc_offset(capture_t *capture)
{
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
#else
codec_input_t *codec = capture->hdl;
#endif
csi_ringbuf_t *adc_fifo = drv_codec_input_fifo_get(codec[0].ch_idx);
uint32_t irq_flag = csi_irq_save();
int offset = (adc_fifo->size * 3 / 4) % 2 ? (adc_fifo->size * 3 / 4) - 1 : (adc_fifo->size * 3 / 4);
adc_fifo->data_len = offset;
if (adc_fifo->write >= adc_fifo->data_len) {
adc_fifo->read = adc_fifo->write - adc_fifo->data_len;
} else {
adc_fifo->read = adc_fifo->size - (adc_fifo->data_len - adc_fifo->write);
}
csi_irq_restore(irq_flag);
for (int i = 1; i < capture->channels; i++) {
if (codec[i].ch_idx != EMPTY_INPUT_CHANNEL) {
adc_fifo = drv_codec_input_fifo_get(codec[i].ch_idx);
uint32_t irq_flag = csi_irq_save();
adc_fifo->data_len = offset;
if (adc_fifo->write >= adc_fifo->data_len) {
adc_fifo->read = adc_fifo->write - adc_fifo->data_len;
} else {
adc_fifo->read = adc_fifo->size - (adc_fifo->data_len - adc_fifo->write);
}
csi_irq_restore(irq_flag);
}
}
return 0;
}
static int g_pcmc_lpm_flag;
static int pcmc_lpm(aos_dev_t *dev, int state)
{
aos_pcm_t *pcm = pcm_dev(dev);
capture_t *capture = (capture_t *)pcm->hdl;
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
#else
codec_input_t *codec = capture->hdl;
#endif
for (int i = 0; i < PANGU_MAX_CHANNELS; i++) {
if (codec->ch_idx == g_snd_ref_id) {
break;
}
codec ++;
}
if (state) {
g_pcmc_lpm_flag = 1;
// close_ref
csi_codec_input_stop(codec);
csi_codec_input_close(codec);
} else {
// open_ref
csi_codec_input_open(codec);
memset(codec->buf, 0, codec->buf_size);
codec_input_config_t config;
config.bit_width = pcm->hw_params->sample_bits;
config.channel_num = pcm->hw_params->channels;
config.sample_rate = pcm->hw_params->rate;
csi_codec_input_config(codec, &config);
csi_codec_input_start(codec);
pcmc_offset(capture);
g_pcmc_lpm_flag = 0;
pcm->event.cb(pcm, PCM_EVT_READ, pcm->event.priv);
}
return 0;
}
static int pcmc_open(aos_dev_t *dev)
{
aos_pcm_t *pcm = pcm_dev(dev);
capture_t *capture = aos_zalloc(sizeof(capture_t));
if (capture) {
pcm->hdl = capture;
capture->state = 0;
return 0;
}
return -1;
}
static int pcmc_close(aos_dev_t *dev)
{
aos_pcm_t *pcm = pcm_dev(dev);
capture_t *capture = (capture_t *)pcm->hdl;
capture_free(capture);
aos_free(capture);
return 0;
}
static int g_input_ch_idx[PANGU_MAX_CHANNELS];
static int g_input_ch_idx_gain[PANGU_MAX_CHANNELS];
static int g_input_ch_flags = 0;
volatile int g_input_flag = 0;
#ifdef CONFIG_CSI_V2
static void input_event_cb(int idx, csi_codec_event_t event, void *arg)
#else
static void input_event_cb(int idx, codec_event_t event, void *arg)
#endif
{
aos_pcm_t *pcm = (aos_pcm_t *)arg;
if (g_pcmc_lpm_flag == 1) {
return;
}
if (event == CODEC_EVENT_PERIOD_READ_COMPLETE) {
g_input_flag |= (1 << idx);
if (g_input_flag == g_input_ch_flags) {
pcm->event.cb(pcm, PCM_EVT_READ, pcm->event.priv);
g_input_flag = 0;
}
} else {
pcm->event.cb(pcm, PCM_EVT_XRUN, pcm->event.priv);
g_input_flag = 0;
}
}
static int pcmc_param_set(aos_pcm_t *pcm, struct aos_pcm_hw_params *params)
{
capture_t *capture = (capture_t *)pcm->hdl;
capture_free(capture);
capture->channels = params->channels;
#ifdef CONFIG_CSI_V2
csi_error_t ret;
capture->hdl = aos_zalloc_check(sizeof(csi_codec_input_t) * capture->channels);
#else
capture->hdl = aos_zalloc_check(sizeof(codec_input_t) * capture->channels);
#endif
CHECK_RET_TAG_WITH_RET(NULL != capture->hdl, -1);
capture->recv = aos_zalloc_check(params->buffer_bytes * capture->channels);
if (capture->recv == NULL) {
goto pcmc_err0;
}
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
csi_codec_input_config_t input_config;
codec->ring_buf = &input_ring_buffer;
#else
codec_input_t *codec = capture->hdl;
codec_input_config_t config;
#endif
uint8_t *recv = (uint8_t *)capture->recv;
#ifdef CONFIG_CSI_V2
codec->ring_buf = &input_ring_buffer;
int buffer_bytes = params->buffer_bytes / capture->channels;
int period = params->period_bytes / capture->channels;
/* input ch config */
for (int i = 0; i < capture->channels; i++) {
csi_codec_input_attach_callback(codec, input_event_cb, NULL);
input_config.bit_width = params->sample_bits;
input_config.sample_rate = params->rate;
input_config.buffer = recv + i * buffer_bytes;
input_config.buffer_size = buffer_bytes;
input_config.period = period;
input_config.mode = CODEC_INPUT_DIFFERENCE;
input_config.sound_channel_num = 1;
if (codec->ch_idx == -1) {
codec ++;
continue;
}
csi_codec_input_config(codec, &input_config);
ret = csi_codec_input_open(&codec_a, codec, g_input_ch_idx[i]);
if (ret != CSI_OK) {
goto pcmc_err1;
}
ret = csi_codec_input_config(codec, &input_config);
if (ret != CSI_OK) {
goto pcmc_err1;
}
if (codec->ch_idx == 4) {//mic
csi_codec_input_analog_gain(codec, 0);
} else {//ref
csi_codec_input_analog_gain(codec, 6);
}
codec ++;
}
#else
config.bit_width = params->sample_bits;
config.sample_rate = params->rate;
config.channel_num = 1;
int buffer_bytes = params->buffer_bytes / capture->channels;
int period = params->period_bytes / capture->channels;
int recv_offset = 0;
for (int i = 0; i < capture->channels; i++) {
codec->buf = recv + recv_offset * buffer_bytes;
codec->cb = input_event_cb;
codec->ch_idx = g_input_ch_idx[i];
codec->buf_size = buffer_bytes;
codec->cb_arg = pcm;
codec->codec_idx = 0;
codec->period = period;
if (codec->ch_idx == -1) {
codec ++;
continue;
}
recv_offset ++;
int ret = csi_codec_input_open(codec);
if (ret != 0) {
goto pcmc_err1;
}
ret = csi_codec_input_config(codec, &config);
if (ret != 0) {
goto pcmc_err1;
}
if (g_input_ch_idx_gain[i] >= 0) {
csi_codec_input_set_analog_gain(codec, g_input_ch_idx_gain[i] > 20 ? 20 : g_input_ch_idx_gain[i]);
csi_codec_input_set_digital_gain(codec, g_input_ch_idx_gain[i] - 20 > 0 ? g_input_ch_idx_gain[i] - 20 : 0);
} else {
csi_codec_input_set_analog_gain(codec, 0);
csi_codec_input_set_digital_gain(codec, 0);
}
codec ++;
}
#endif
aos_kernel_sched_suspend();
codec = capture->hdl;
for (int i = 0; i < capture->channels; i++) {
if (codec->ch_idx != -1) {
csi_codec_input_start(codec);
}
codec ++;
}
aos_kernel_sched_resume();
capture->state = 1;
memcpy(&capture->params, params, sizeof(aos_pcm_hw_params_t));
return 0;
pcmc_err1:
aos_free(capture->hdl);
pcmc_err0:
aos_free(capture->hdl);
return -1;
}
static int pcm_recv(aos_pcm_t *pcm, void *buf, int size)
{
capture_t *capture = (capture_t *)pcm->hdl;
int ret = -1;
int i;
static int cnt = 0;
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
#else
codec_input_t *codec = capture->hdl;
#endif
char *recv = buf;
int recv_size = size / capture->channels;
for (i = 0; i < capture->channels; i++) {
if (codec->ch_idx != -1) {
ret = csi_codec_input_read(codec, (uint8_t *)recv, recv_size);
if (ret != recv_size) {
// asm("bkpt");
if (100 == ++cnt) {
printf("\n\n>> Warning codec_input_read(%d,%d)\n\n", ret, recv_size);
cnt = 0;
}
}
} else {
memset(recv, 0x00, recv_size);
ret = recv_size;
}
if (ret != recv_size) {
break;
}
recv += recv_size;
codec ++;
}
return (ret * i);
}
static int pcmc_get_remain_size(aos_pcm_t *pcm)
{
capture_t *capture = (capture_t *)pcm->hdl;
#ifdef CONFIG_CSI_V2
csi_codec_input_t *codec = capture->hdl;
#else
codec_input_t *codec = capture->hdl;
#endif
int ret = 0x7fffffff;
for (int i = 0; i < capture->channels; i++) {
#ifdef CONFIG_CSI_V2
if (codec->ch_idx != 0xffffffff ) {
#else
if (codec->ch_idx >= 0 ) {
#endif
int avail = 0;
#ifdef CONFIG_CSI_V2
avail = csi_codec_input_buffer_avail(codec);
#else
avail = csi_codec_input_buf_avail(codec);
#endif
if (avail < ret) {
ret = avail;
}
}
codec ++;
}
return ret * capture->channels;
}
static aos_pcm_drv_t aos_pcm_drv[] = {
{
.drv = {
.name = "pcmP",
.init = pcm_init,
.uninit = pcm_uninit,
.open = pcmp_open,
.close = pcmp_close,
.lpm = pcmp_lpm,
},
.ops = {
.hw_params_set = pcmp_param_set,
.write = pcm_send,
.pause = pcm_pause,
},
},
{
.drv = {
.name = "pcmC",
.init = pcm_init,
.uninit = pcm_uninit,
.open = pcmc_open,
.close = pcmc_close,
.lpm = pcmc_lpm,
},
.ops = {
.hw_params_set = pcmc_param_set,
.read = pcm_recv,
.hw_get_remain_size = pcmc_get_remain_size,
},
}
};
static int aos_pcm_register(void)
{
driver_register(&aos_pcm_drv[0].drv, NULL, 0);
driver_register(&aos_pcm_drv[1].drv, NULL, 0);
// driver_register(&aos_pcm_drv[1].drv, NULL, 2);
// driver_register(&aos_pcm_drv[1].drv, NULL, 1);
return 0;
}
static int aos_pcm_unregister(void)
{
driver_unregister("pcmP0");
return 0;
}
static aos_dev_t *card_init(driver_t *drv, void *config, int id)
{
card_dev_t *card = (card_dev_t *)device_new(drv, sizeof(card_dev_t), id);
snd_card_drv_t *card_drv = (snd_card_drv_t *)drv;
aos_mixer_elem_t *elem;
#ifdef CONFIG_CSI_V2
csi_error_t ret;
ret = csi_codec_init(&codec_a, 0);
if (ret != CSI_OK) {
printf("csi_codec_init error\n");
}
#else
csi_codec_init(id);
#endif
//FIXME: must sleep 500ms at least before PA ON, otherwise baoyin happens
// aos_msleep(500);
aos_pcm_register();
slist_init(&card_drv->mixer_head);
snd_elem_new(&elem, "codec0", &elem_codec1_ops);
slist_add(&elem->next, &card_drv->mixer_head);
memset(&mixp0, 0, sizeof(mixer_playback_t));
mixp0.mute = -1;
return (aos_dev_t *)card;
}
static void card_uninit(aos_dev_t *dev)
{
//TODO free mixer elem;
#ifdef CONFIG_CSI_V2
csi_codec_uninit(&codec_a);
#else
csi_codec_uninit(dev->id);
#endif
aos_pcm_unregister();
device_free(dev);
}
static int card_open(aos_dev_t *dev)
{
return 0;
}
static int card_close(aos_dev_t *dev)
{
return 0;
}
static int card_lpm(aos_dev_t *dev, int state)
{
#ifdef CONFIG_CSI_V2
#else
if (state > 0) {
csi_codec_lpm(dev->id, CODEC_MODE_SLEEP);
} else {
csi_codec_lpm(dev->id, CODEC_MODE_RUN);
}
#endif
return 0;
}
static snd_card_drv_t snd_card_drv = {
.drv = {
.name = "card",
.init = card_init,
.uninit = card_uninit,
.open = card_open,
.close = card_close,
.lpm = card_lpm,
}
};
void snd_card_pangu_register(void *config)
{
snd_pangu_config_t *pangu_config = (snd_pangu_config_t *)config;
aos_check_param(pangu_config->id_list && pangu_config->id_num > 0 && pangu_config->id_num <= PANGU_MAX_CHANNELS);
g_snd_ref_id = pangu_config->snd_ref_id;
g_input_ch_flags = 0;
for (int i = 0; i < PANGU_MAX_CHANNELS; ++i) {
if (pangu_config->id_list[i] < 0 || i >= pangu_config->id_num) {
g_input_ch_idx[i] = -1;
continue;
}
g_input_ch_flags |= 1 << pangu_config->id_list[i];
g_input_ch_idx[i] = pangu_config->id_list[i];
g_input_ch_idx_gain[i] = pangu_config->gain_list[i];
}
if (pangu_config->dac_db_max < 0 && pangu_config->dac_db_max >= -62 &&
pangu_config->dac_db_min < 0 && pangu_config->dac_db_min >= -62 &&
pangu_config->dac_db_min <= pangu_config->dac_db_max) { /* == debug mode */
g_dac_gain_max = pangu_config->dac_db_max;
g_dac_gain_min = pangu_config->dac_db_min;
}
if (g_dac_gain_min == g_dac_gain_max) {
mixp0.l = mixp0.r = g_dac_gain_max;
}
driver_register(&snd_card_drv.drv, NULL, 0);
}
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yocop/drv_snd_pangu.git
[email protected]:yocop/drv_snd_pangu.git
yocop
drv_snd_pangu
drv_snd_pangu
master

搜索帮助