MTK平台 I2S音频——接收外部I2S数据
而SetIntfConnectionFormat这个函数在mtk-soc-afe-connnection.h,关键的来了我并没有在同文件夹下发现mtk-soc-afe-connnection.c ,但是编译并没有报错。这里使用的是主机模式,但是一开始的外部IC是作主机的,但发现主控MT型号的I2S0并不可以作为从机模式,因此改变为主控为主机!这里的stream_name、cpu_dai_name、
项目的总体框架图是这样的
在这个kernel-4.19\sound\soc\mediatek\common_int目录下修改和添加的文件有
add
mtk-soc-pcm-i2s0-capture.c
modified
kernel-4.19\arch\arm64\boot\dts\mediatek\<your project >.dts
makefile
mtk-auddrv-def.h
mtk-auddrv-gpio.c
mtk-auddrv-gpio.h
mtk-soc-dai-stub.c
mtk-soc-machine.c
在kernel-4.19\sound\soc\mediatek\common_int中添加一个PCM
mtk-soc-pcm-i2s0-capture.c
/*
* Copyright (C) 2015 MediaTek Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
*
* Filename:
* ---------
* mtk_osc_pcm_I2S0_capture.c
*
* Project:
* --------
* Audio Driver Kernel Function
*
* Description:
* ------------
* Audio I2S0 to capture capture
*
* Author:
* -------
*
*
*----------------------------------------------------------------------------
*
*
****************************************************************************
*/
/*****************************************************************************
* C O M P I L E R F L A G S
*****************************************************************************/
/*****************************************************************************
* E X T E R N A L R E F E R E N C E S
*****************************************************************************/
#include <linux/dma-mapping.h>
#include <sound/pcm_params.h>
#include "mtk-auddrv-afe.h"
#include "mtk-auddrv-ana.h"
#include "mtk-auddrv-clk.h"
#include "mtk-auddrv-common.h"
#include "mtk-auddrv-def.h"
#include "mtk-auddrv-kernel.h"
#include "mtk-auddrv-gpio.h"
#include "mtk-soc-afe-control.h"
#include "mtk-soc-pcm-common.h"
#include "mtk-soc-pcm-platform.h"
#include "mtk-soc-digital-type.h"
static struct afe_mem_control_t *I2S0_Capture_Control_context;
static struct snd_dma_buffer *I2S0_Capture_dma_buf;
static unsigned int mPlaybackDramState;
//static struct device *mDev;
#define I2S0_Capture_MAX_BUFFER_SIZE (64 * 1024)
#define I2S0_Capture_MIN_PERIOD_SIZE 1
#define I2S0_Capture_MAX_PERIOD_SIZE (64 * 1024)
static struct audio_digital_i2s *mAudioDigitalI2S;
#ifdef CONFIG_ZLT_CODEC_DEBUG
#define ZLT_PRINTK printk
#else
#define ZLT_PRINTK pr_err
#endif
/*
* function implementation
*/
static void StartAudioI2S0CaptureHardware(struct snd_pcm_substream *substream);
static void StopAudioI2S0captureHardware(struct snd_pcm_substream *substream);
static int mtk_I2S0_capture_probe(struct platform_device *pdev);
static int mtk_I2S0_capture_pcm_close(struct snd_pcm_substream *substream);
static int mtk_I2S0_capture_data_probe(struct snd_soc_component *platform);
static struct snd_pcm_hardware mtk_I2S0_capture_hardware = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SND_SOC_ADV_MT_FMTS,
.rates = SOC_HIGH_USE_RATE,
.rate_min = SOC_HIGH_USE_RATE_MIN,
.rate_max = SOC_HIGH_USE_RATE_MAX,
.channels_min = SOC_NORMAL_USE_CHANNELS_MIN,
.channels_max = SOC_NORMAL_USE_CHANNELS_MAX,
.buffer_bytes_max = I2S0_Capture_MAX_BUFFER_SIZE,
.period_bytes_max = I2S0_Capture_MAX_BUFFER_SIZE,
.periods_min = I2S0_Capture_MIN_PERIOD_SIZE,
.periods_max = I2S0_Capture_MAX_PERIOD_SIZE,
.fifo_size = 0,
};
static void StopAudioI2S0captureHardware(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("StopAudioI2S0captureHardware\n");
SetIntfConnection(Soc_Aud_InterCon_DisConnect,
Soc_Aud_AFE_IO_Block_I2S0,
Soc_Aud_AFE_IO_Block_MEM_VUL2);
SetExtI2S0AdcInEnable(false);
SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_VUL2, false);
irq_remove_user(
substream,
irq_request_number(Soc_Aud_Digital_Block_MEM_VUL2));
EnableAfe(false);
}
static void ConfigAdcI2S(struct snd_pcm_substream *substream)
{
mAudioDigitalI2S->mI2S_IN_PAD_SEL = Soc_Aud_I2S_IN_PAD_SEL_I2S_IN_FROM_IO_MUX;
mAudioDigitalI2S->mI2S_SLAVE = Soc_Aud_I2S_SRC_MASTER_MODE;
mAudioDigitalI2S->mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
mAudioDigitalI2S->mloopback = 0;
mAudioDigitalI2S->mI2S_HDEN = Soc_Aud_LOW_JITTER_CLOCK;
mAudioDigitalI2S->mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
mAudioDigitalI2S->mI2S_SAMPLERATE = (substream->runtime->rate);
if (substream->runtime->format == SNDRV_PCM_FORMAT_S32_LE ||
substream->runtime->format == SNDRV_PCM_FORMAT_U32_LE)
mAudioDigitalI2S->mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_32BITS;
else
mAudioDigitalI2S->mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
}
static void StartAudioI2S0CaptureHardware(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("StartAudioI2S0CaptureHardware,rate=%d,format=%d,period_size=%lu,period_count=%u,channel=%d\n",substream->runtime->rate,substream->runtime->format,
substream->runtime->period_size,substream->runtime->periods,substream->runtime->channels);
/* here to set interrupt */
irq_add_user(substream,
irq_request_number(Soc_Aud_Digital_Block_MEM_VUL2),
substream->runtime->rate, substream->runtime->period_size);
SetSampleRate(Soc_Aud_Digital_Block_MEM_VUL2,substream->runtime->rate);
SetChannels(Soc_Aud_Digital_Block_MEM_VUL2, substream->runtime->channels);
SetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_VUL2, true);
EnableAfe(true);
}
static int mtk_I2S0_capture_alsa_stop(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("mtk_I2S0_capture_alsa_stop\n");
StopAudioI2S0captureHardware(substream);
RemoveMemifSubStream(Soc_Aud_Digital_Block_MEM_VUL2, substream);
return 0;
}
static int mtk_I2S0_capture_pcm_prepare(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("%s substream->rate = %d channels = %d\n",
__func__, substream->runtime->rate,
substream->runtime->channels);
if (substream->runtime->format == SNDRV_PCM_FORMAT_S32_LE ||
substream->runtime->format == SNDRV_PCM_FORMAT_U32_LE) {
SetConnectionFormat(OUTPUT_DATA_FORMAT_24BIT,Soc_Aud_AFE_IO_Block_MEM_VUL2);
SetMemIfFetchFormatPerSample(Soc_Aud_Digital_Block_MEM_VUL2,AFE_WLEN_32_BIT_ALIGN_24BIT_DATA_8BIT_0);
} else {
SetConnectionFormat(OUTPUT_DATA_FORMAT_16BIT,Soc_Aud_AFE_IO_Block_MEM_VUL2);
SetMemIfFetchFormatPerSample(Soc_Aud_Digital_Block_MEM_VUL2, AFE_WLEN_16_BIT);
}
EnableALLbySampleRate(substream->runtime->rate);
EnableAPLLTunerbySampleRate(substream->runtime->rate);
SetCLkMclk(Soc_Aud_I2S0,substream->runtime->rate); /* select I2S */
EnableI2SCLKDiv(Soc_Aud_I2S0_MCKDIV, true);
ConfigAdcI2S(substream);
SetExtI2S0AdcIn(mAudioDigitalI2S);
SetExtI2S0AdcInEnable(true);
SetIntfConnection(Soc_Aud_InterCon_Connection,
Soc_Aud_AFE_IO_Block_I2S0,
Soc_Aud_AFE_IO_Block_MEM_VUL2);
return 0;
}
static snd_pcm_uframes_t mtk_I2S0_capture_pcm_pointer(struct snd_pcm_substream *substream)
{
return get_mem_frame_index(substream, I2S0_Capture_Control_context,
Soc_Aud_Digital_Block_MEM_VUL2);
}
static int mtk_I2S0_capture_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
int ret = 0;
dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
dma_buf->dev.dev = substream->pcm->card->dev;
dma_buf->private_data = NULL;
substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
//substream->runtime->dma_bytes = 32768;
if (I2S0_Capture_dma_buf->area) {
pr_err("mtk_I2S0_capture_pcm_hw_params 1\n");
runtime->dma_bytes = params_buffer_bytes(hw_params);
runtime->dma_area = I2S0_Capture_dma_buf->area;
runtime->dma_addr = I2S0_Capture_dma_buf->addr;
SetHighAddr(Soc_Aud_Digital_Block_MEM_VUL2, true,
runtime->dma_addr);
mPlaybackDramState = true;
AudDrv_Emi_Clk_On();
} else {
pr_err("mtk_I2S0_capture_pcm_hw_params 2\n");
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
ZLT_PRINTK("mtk_I2S0_capture_pcm_hw_params dma_bytes = %zu dma_area = %p dma_addr = 0x%lx\n",
runtime->dma_bytes, runtime->dma_area, (long)runtime->dma_addr);
set_mem_block(substream, hw_params, I2S0_Capture_Control_context,
Soc_Aud_Digital_Block_MEM_VUL2);
return ret;
}
static int mtk_I2S0_capture_capture_pcm_hw_free(struct snd_pcm_substream *substream)
{
pr_err("mtk_I2S0_capture_capture_pcm_hw_free\n");
if (I2S0_Capture_dma_buf->area) {
if (mPlaybackDramState == true) {
AudDrv_Emi_Clk_Off();
mPlaybackDramState = false;
} else
freeAudioSram((void *)substream);
return 0;
} else
return snd_pcm_lib_free_pages(substream);
}
static struct snd_pcm_hw_constraint_list dl1_awb_constraints_sample_rates = {
.count = ARRAY_SIZE(soc_high_supported_sample_rates),
.list = soc_high_supported_sample_rates,
};
static int mtk_I2S0_capture_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret = 0;
mPlaybackDramState = false;
ZLT_PRINTK("mtk_I2S0_capture_pcm_open\n");
I2S0_Capture_Control_context =
Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_VUL2);
runtime->hw = mtk_I2S0_capture_hardware;
memcpy((void *)(&(runtime->hw)), (void *)&mtk_I2S0_capture_hardware,
sizeof(struct snd_pcm_hardware));
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&dl1_awb_constraints_sample_rates);
ret = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
pr_info("snd_pcm_hw_constraint_integer failed\n");
runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
if (ret < 0) {
pr_err("mtk_I2S0_capture_pcm_close\n");
mtk_I2S0_capture_pcm_close(substream);
return ret;
}
AudDrv_Clk_On();
pr_err("mtk_I2S0_capture_pcm_open return\n");
return 0;
}
static int mtk_I2S0_capture_pcm_close(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("mtk_I2S0_capture_pcm_close substream->runtime->rate = %d\n", substream->runtime->rate);
DisableAPLLTunerbySampleRate(substream->runtime->rate);
DisableALLbySampleRate(substream->runtime->rate);
AudDrv_Clk_Off();
return 0;
}
static int mtk_I2S0_capture_alsa_start(struct snd_pcm_substream *substream)
{
ZLT_PRINTK("mtk_I2S0_capture_alsa_start\n");
//mtk_soc_always_hd = 1;
SetMemifSubStream(Soc_Aud_Digital_Block_MEM_VUL2, substream);
StartAudioI2S0CaptureHardware(substream);
return 0;
}
static int mtk_I2S0_capture_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
{
pr_err("mtk_I2S0_capture_pcm_trigger cmd = %d\n", cmd);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
return mtk_I2S0_capture_alsa_start(substream);
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
return mtk_I2S0_capture_alsa_stop(substream);
}
return -EINVAL;
}
static int mtk_I2S0_capture_pcm_copy(struct snd_pcm_substream *substream,
int channel, unsigned long pos,
void __user *dst, unsigned long count)
{
return mtk_memblk_copy(substream, channel, pos, dst, count,
I2S0_Capture_Control_context,
Soc_Aud_Digital_Block_MEM_VUL2);
}
static void *dummy_page[2];
static struct page *mtk_I2S0_capture_pcm_page(struct snd_pcm_substream *substream,
unsigned long offset)
{
return virt_to_page(dummy_page[substream->stream]); /* the same page */
}
static struct snd_pcm_ops mtk_I2S0_capture_ops = {
.open = mtk_I2S0_capture_pcm_open,
.close = mtk_I2S0_capture_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.prepare = mtk_I2S0_capture_pcm_prepare,
.hw_params = mtk_I2S0_capture_pcm_hw_params,
.hw_free = mtk_I2S0_capture_capture_pcm_hw_free,
.trigger = mtk_I2S0_capture_pcm_trigger,
.pointer = mtk_I2S0_capture_pcm_pointer,
.copy_user = mtk_I2S0_capture_pcm_copy,
.page = mtk_I2S0_capture_pcm_page,
};
static struct snd_soc_component_driver mtk_soc_platform = {
.name = AFE_PCM_NAME,
.ops = &mtk_I2S0_capture_ops,
.probe = mtk_I2S0_capture_data_probe,
};
static int mtk_I2S0_capture_probe(struct platform_device *pdev)
{
pr_err("mtk_I2S0_capture_probe\n");
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
mAudioDigitalI2S = kzalloc(sizeof(struct audio_digital_i2s), GFP_KERNEL);
if (pdev->dev.of_node)
dev_set_name(&pdev->dev, "%s", MT_SOC_I2S0_Capture_PCM);
pdev->name = pdev->dev.kobj.name;
pr_err("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
//mDev = &pdev->dev;
return snd_soc_register_component(&pdev->dev, &mtk_soc_platform, NULL, 0);
}
static int mtk_I2S0_capture_data_probe(struct snd_soc_component *platform)
{
pr_err("mtk_I2S0_capture_data_probe\n");
AudDrv_Allocate_mem_Buffer(platform->dev, Soc_Aud_Digital_Block_MEM_VUL2,
UL2_MAX_BUFFER_SIZE);
I2S0_Capture_dma_buf = Get_Mem_Buffer(Soc_Aud_Digital_Block_MEM_VUL2);
return 0;
}
static int mtk_I2S0_capture_remove(struct platform_device *pdev)
{
pr_err("%s\n", __func__);
snd_soc_unregister_component(&pdev->dev);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id mt_soc_pcm_I2S0_capture_of_ids[] = {
{
.compatible = "mediatek,mt_soc_pcm_I2S0_capture",
},
{} };
#endif
static struct platform_driver mtk_I2S0_capture_capture_driver = {
.driver = {
.name = MT_SOC_I2S0_Capture_PCM,
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = mt_soc_pcm_I2S0_capture_of_ids,
#endif
},
.probe = mtk_I2S0_capture_probe,
.remove = mtk_I2S0_capture_remove,
};
//static struct platform_device *soc_I2S0_capture_capture_dev;
static int __init mtk_soc_I2S0_capture_platform_init(void)
{
int ret = 0;
pr_err("%s\n", __func__);
/*
soc_I2S0_capture_capture_dev =
platform_device_alloc(MT_SOC_I2S0_Capture_PCM, -1);
if (!soc_I2S0_capture_capture_dev)
return -ENOMEM;
ret = platform_device_add(soc_I2S0_capture_capture_dev);
if (ret != 0) {
platform_device_put(soc_I2S0_capture_capture_dev);
return ret;
}
*/
ret = platform_driver_register(&mtk_I2S0_capture_capture_driver);
return ret;
}
static void __exit mtk_soc_I2S0_capture_platform_exit(void)
{
platform_driver_unregister(&mtk_I2S0_capture_capture_driver);
}
module_init(mtk_soc_I2S0_capture_platform_init);
module_exit(mtk_soc_I2S0_capture_platform_exit);
MODULE_DESCRIPTION("I2S0 Capture module platform driver");
MODULE_LICENSE("GPL");
这里需要注意的是连接I2S的需要作从机还是主机
mAudioDigitalI2S->mI2S_SLAVE = Soc_Aud_I2S_SRC_MASTER_MODE;
这里使用的是主机模式,但是一开始的外部IC是作主机的,但发现主控MT型号的I2S0并不可以作为从机模式,因此改变为主控为主机!!!
确认I2S是否可以作SLAVE 需要查看主控的数据手册
kernel-4.19\arch\arm64\boot\dts\mediatek\<your project >.dts
&audgpio {
pinctrl-names =
//other pinctrl-names
"extamp-pulllow",
"extamp-pullhigh",
"is0_mode_off",
"is0_mode_on";
//other pinctrl
pinctrl-10 = <&aud_pins_extamp_low>;
pinctrl-11 = <&aud_pins_extamp_high>;
pinctrl-12 = <&aud_pins_i2s0_off>;
pinctrl-13 = <&aud_pins_i2s0_on>;
};
//记得添加对应的GPIO引脚
&pio {
aud_pins_extamp_low: aud_pins_extamp_low {
pins_cmd_dat {
pinmux = <PINMUX_GPIO4__FUNC_GPIO4>;
slew-rate = <1>;
output-low;
};
};
aud_pins_extamp_high: aud_pins_extamp_high {
pins_cmd_dat {
pinmux = <PINMUX_GPIO4__FUNC_GPIO4>;
slew-rate = <1>;
output-high;
};
};
aud_pins_i2s0_off: i2s0_mode0 {
pins_cmd0_dat {
pinmux = <PINMUX_GPIO0__FUNC_GPIO0>;
input-enable;
slew-rate = <0>;
bias-disable;
};
pins_cmd1_dat {
pinmux = <PINMUX_GPIO1__FUNC_GPIO1>;
input-enable;
slew-rate = <0>;
bias-disable;
};
pins_cmd2_dat {
pinmux = <PINMUX_GPIO2__FUNC_GPIO2>;
input-enable;
slew-rate = <0>;
bias-disable;
};
pins_cmd3_dat {
pinmux = <PINMUX_GPIO3__FUNC_GPIO3>;
input-enable;
slew-rate = <0>;
bias-disable;
};
};
aud_pins_i2s0_on: i2s0_mode1 {
pins_cmd0_dat {
pinmux = <PINMUX_GPIO0__FUNC_I2S0_MCK>;
};
pins_cmd1_dat {
pinmux = <PINMUX_GPIO1__FUNC_I2S0_BCK>;
};
pins_cmd2_dat {
pinmux = <PINMUX_GPIO2__FUNC_I2S0_LRCK>;
};
pins_cmd3_dat {
pinmux = <PINMUX_GPIO3__FUNC_I2S0_DI>;
};
};
makefile添加obj-y += mtk-soc-pcm-i2s0-capture.o 让他编译上
mtk-auddrv-def.h 添加对应的
/* AFE PCM name */
/* codec dai name */
/* stream name */
mtk-auddrv-gpio.c
//在这里添加你在设备树加入的 pinctrl-name
enum audio_system_gpio_type {
// Other code
GPIO_I2S0_MODE0,
GPIO_I2S0_MODE1,
GPIO_EXTAMP_HIGH,
GPIO_EXTAMP_LOW,
// Other code
};
static struct audio_gpio_attr aud_gpios[GPIO_NUM] = {
// Other code
[GPIO_I2S0_MODE0] = {"is0_mode_off", false, NULL},
[GPIO_I2S0_MODE1] = {"is0_mode_on", false, NULL},
[GPIO_EXTAMP_HIGH] = {"extamp-pullhigh", false, NULL},
[GPIO_EXTAMP_LOW] = {"extamp-pulllow", false, NULL},
// Other code
};
void AudDrv_GPIO_probe(void *dev)
{
// Other code
AudDrv_GPIO_I2S0_Select(1);
// Other code
}
mtk-auddrv-gpio.h
int AudDrv_GPIO_I2S0_Select(int bEnable);
mtk-soc-dai-stub.c
static struct snd_soc_dai_driver mtk_dai_stub_dai[] = {
//other code
{
.capture = {
.stream_name = MT_SOC_I2S0_CAPTURE_NAME,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SND_SOC_ADV_MT_FMTS,
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 192000,
},
.name = MT_SOC_I2S0CAPTUREDAI_NAME,
.ops = &mtk_dai_stub_ops,
},
//other code
};
mtk-soc-machine.c
这里的stream_name、cpu_dai_name、platform_name 就是对应mtk-auddrv-def.h的名字
static struct snd_soc_dai_link mt_soc_dai_common[] = {
//other code
{
.name = "I2S0Capture",
.stream_name = MT_SOC_I2S0_CAPTURE_NAME,
.cpu_dai_name = MT_SOC_I2S0CAPTUREDAI_NAME,
.platform_name = MT_SOC_I2S0_Capture_PCM,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.dpcm_capture = 1,
},
//other code
};
完成后编译
adb root
adb shell cat proc/asound/pcm
00-30: I2S0_CAPTURE snd-soc-dummy-dai-30 : : capture 1
#若出现你对应mtk-auddrv-def.h 取得名字I2S0_CAPTURE 即为成功
#使用如下命令录音
adb shell tinycap sdcard/test.pcm -D 00 -d 30 -c 2 -r 44100 -b 16
之后在拉下来
adb pull /sdcard/test.pcm
查看这个音频有没有数据,有就成功了
但是事情有这么简单吗??
我在这里遇到了问题
链路未打通,通过查看数据手册
我们这里的是从I_0 I_1 到O_32 O_33
那么就是要把这个链路打通
并且tinycap 录的就是O口的数据,那么需要I口与O口连接且I口有数据即可;
但是我这个版本有一个巨大坑
这里是通过
SetIntfConnection(Soc_Aud_InterCon_Connection,
Soc_Aud_AFE_IO_Block_I2S0,
Soc_Aud_AFE_IO_Block_MEM_VUL2);
这个函数链接 i2S0 TO VUL2,那么对应的寄存器就是AFE_CONN32 和AFE_CONN33
我们可以通过adb shell cat /sys/kernel/debug/mtksocaudio查看寄存器,发现AFE_CONN32和AFE_CONN33都是0x0
SetIntfConnection这个函数是在mtk-soc-afe-control.c里
bool SetConnectionFormat(unsigned int ConnectionFormat, unsigned int Aud_block)
{
return SetIntfConnectionFormat(ConnectionFormat, Aud_block);
}
而SetIntfConnectionFormat这个函数在mtk-soc-afe-connnection.h,关键的来了我并没有在同文件夹下发现mtk-soc-afe-connnection.c ,但是编译并没有报错
我通过抓取这个函数发现他在mt6765和mt6739都有
grep -r "SetIntfConnectionFormat" sound/soc/mediatek/
那么我们就可以在
out\target\product\k61v1_64_bsp\obj\KERNEL_OBJ\sound\soc\mediate
发现确实他是编译了MT6765的mtk-soc-afe-connnection.c
那么我们找到MT6765的mtk-soc-afe-connnection.c发现
SetIntfConnection这个函数居然没有如下内容,
static const struct connection_link_t mConnectionLink[] = {
//other code
{Soc_Aud_AFE_IO_Block_I2S0,
Soc_Aud_AFE_IO_Block_MEM_VUL2, SetI2s0ToVul2},
//other code
};
bool SetIntfConnectionFormat(unsigned int ConnectionFormat,
unsigned int Aud_block)
{
//other code
case Soc_Aud_AFE_IO_Block_MEM_VUL2: {
SetoutputConnectionFormat(ConnectionFormat,
Soc_Aud_InterConnectionOutput_O32); // 对应AFE_CONN32
SetoutputConnectionFormat(ConnectionFormat,
Soc_Aud_InterConnectionOutput_O33); // 对应AFE_CONN33
break;
}
//other code
};
当我加上这个后编译打包烧录
发现录音时就有声音了并且录音时adb shell cat /sys/kernel/debug/mtksocaudio
AFE_CONN32 = 0x1
AFE_CONN33= 0x2
也成功了
并且拉下来的文件也有音频数据
更多推荐
所有评论(0)