项目的总体框架图是这样的

在这个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
也成功了

并且拉下来的文件也有音频数据

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐