【I2S-未解决】Milk-V Duo添加tinyplay工具(i2s2 TX Reset失败)

前言

虽然添加好了tinyplay工具,以及pcm设备,但是依然无法播放。

目前看起来问题出现在i2s2的添加上,i2s2 tx reset失败。
如果有了解如何解决的方法,请多指教。

tinyalsa

duo-buildroot-sdk-develop\buildroot-2021.05\package\tinyalsa\Config.in

有依赖关系
BR2_PACKAGE_TINYALSA
BR2_STATIC_LIBS

config BR2_PACKAGE_TINYALSA
	bool "tinyalsa"
	depends on !BR2_STATIC_LIBS
	help
	  a small library to interface with ALSA in the Linux kernel

	  The aims are:

	  - Provide a basic pcm and mixer API
	  - If it's not absolutely needed, don't add it to the API
	  - Avoid supporting complex and unnecessary operations that
	    could be dealt with at a higher level

	  https://github.com/tinyalsa/tinyalsa

comment "tinyalsa needs a toolchain w/ dynamic library"
	depends on BR2_STATIC_LIBS

duo的br配置
duo-buildroot-sdk-develop\buildroot-2021.05\configs\milkv_duo_musl_riscv64_defconfig

BR2_PACKAGE_TINYALSA=y

查看最终打开的br config
duo-buildroot-sdk-develop\buildroot-2021.05\Config.in

打开后生成在dl目录下
duo-buildroot-sdk-develop\buildroot-2021.05\dl

参考资料:https://zhuanlan.zhihu.com/p/508579943

tinyalsa.mk
这里指定了版本

选择下载1.1.1的zip文件

################################################################################
#
# tinyalsa
#
################################################################################

TINYALSA_VERSION = 1.1.1
TINYALSA_SITE = $(call github,tinyalsa,tinyalsa,$(TINYALSA_VERSION))
TINYALSA_LICENSE = BSD-3-Clause
TINYALSA_LICENSE_FILES = NOTICE
TINYALSA_INSTALL_STAGING = YES

define TINYALSA_BUILD_CMDS
	$(TARGET_MAKE_ENV) $(MAKE) CROSS_COMPILE="$(TARGET_CROSS)" -C $(@D)
endef

define TINYALSA_INSTALL_STAGING_CMDS
	$(TARGET_MAKE_ENV) $(MAKE) \
		-C $(@D) \
		PREFIX="/usr" \
		CROSS_COMPILE="$(TARGET_CROSS)" \
		DESTDIR="$(STAGING_DIR)" install
endef

define TINYALSA_INSTALL_TARGET_CMDS
	$(TARGET_MAKE_ENV) $(MAKE) \
		-C $(@D) \
		PREFIX="/usr" \
		CROSS_COMPILE="$(TARGET_CROSS)" \
		DESTDIR="$(TARGET_DIR)" install
endef

$(eval $(generic-package))

image

问题1:tinyplay无法执行,缺失so

image

文件是生成了的,但是没有办法运行。

image

执行file tinyplay可以看到依赖一个库ld-musl-riscv64.so.1
去sdk中搜索
路径:duo-buildroot-sdk\host-tools\gcc\riscv64-linux-musl-x86_64\sysroot\lib\ld-musl-riscv64.so.1

image

方法1:拷贝so

将这个依赖的so放到设备中,可以运行tinyplay了,但是提醒权限


image

没有将so设置权限

chmod 777 /lib/ld-musl-riscv64.so.1

设置完权限后,执行tinyplay命令,可以看到命令可以执行成功并提示需要的参数。

方法2:软连接指向

duo-buildroot-sdk-develop\milkv\overlay\mnt\system\rndis.sh

#!/bin/sh

ln -s /lib/ld-musl-riscv64v0p7_xthead.so.1 /lib/ld-musl-riscv64.so.1

问题2:I2S tx重置失败

pcm设备创建成功可以在两个地方看。

ls -l /dev/snd
cat /proc/asound/pcm

tinyplay可以执行,但是发现tx reset失败。

tinyplay /root/cut76.wav -D 0 -d 0

image

发现执行后提示播放失败。
log来看提示I2S TX RESET failed.

推测1:i2s2的dma配置

推测可能是dtsi中的默认定义i2s2有tx和rx,我暂时只用了rx,导致tx没有reset。

duo-buildroot-sdk-develop\build\boards\default\dts\cv180x\cv180x_base.dtsi

	i2s2: i2s@04120000 {
		compatible = "cvitek,cv1835-i2s";
		reg = <0x0 0x04120000 0x0 0x2000>;
		clocks = <&i2s_mclk 0>;
		clock-names = "i2sclk";
		dev-id = <2>;
		#sound-dai-cells = <0>;
		dmas = <&dmac 6 1 1 /* read channel */
			&dmac 1 1 1>; /* write channel */
		dma-names = "rx", "tx";
		capability = "txrx";
		mclk_out = "false";
	};

默认i2s2是打开了tx和rx的。
tx为传输数据(播放),rx为接收数据(录制)
所以合理的配置应该是

	i2s2: i2s@04120000 {
		compatible = "cvitek,cv1835-i2s";
		reg = <0x0 0x04120000 0x0 0x2000>;
		clocks = <&i2s_mclk 0>;
		clock-names = "i2sclk";
		dev-id = <2>;
		#sound-dai-cells = <0>;
		dmas = <&dmac 1 1 1>; /* write channel */
		dma-names = "tx";
		capability = "tx";
		mclk_out = "false";
	};

这样配置,i2s2就只支持一个dma,也可以看到pcmc0d0。

&i2s2 {
	status = "okay";
	#sound-dai-cells = <0>;
};

&i2s1 {
	status = "okay";
	#sound-dai-cells = <0>;
};


&ethernet0 {
	status="disabled";
};

未解

问题依旧存在。

查看debug信息

image

如图,i2s2其实没有真的起来,查看代码

duo-buildroot-sdk\linux_5.10\sound\soc\cvitek\cv1835_i2s.c

static int i2s_proc_show(struct seq_file *m, void *v)
{
	struct cvi_i2s_dev *dev = m->private;

	if (i2s_read_reg(dev->i2s_base, I2S_ENABLE))
		seq_printf(m, "\ni2s%d is enabled\n", dev->dev_id);
	else
		seq_printf(m, "\ni2s%d is disabled\n", dev->dev_id);

	seq_printf(m, "\n===== Dump I2S%d register status =====\n", dev->dev_id);

	seq_printf(m, "\nblk_mode=0x%08x,          clk_ctrl=0x%08x,          int_en=0x%08x\n",
		   i2s_read_reg(dev->i2s_base, BLK_MODE_SETTING),
		   i2s_read_reg(dev->i2s_base, I2S_CLK_CTRL0),
		   i2s_read_reg(dev->i2s_base, I2S_INT_EN));

	seq_printf(m, "\nframe_setting=0x%08x,     slot_setting=0x%08x,      data_format=0x%08x\n",
		   i2s_read_reg(dev->i2s_base, FRAME_SETTING),
		   i2s_read_reg(dev->i2s_base, SLOT_SETTING1),
		   i2s_read_reg(dev->i2s_base, DATA_FORMAT));

	seq_printf(m, "\ni2s_int=0x%08x,           rx_status=0x%08x,         tx_status=0x%08x\n",
		   i2s_read_reg(dev->i2s_base, I2S_INT),
		   i2s_read_reg(dev->i2s_base, RX_STATUS),
		   i2s_read_reg(dev->i2s_base, TX_STATUS));

	seq_printf(m, "\ndma_req=0x%08x,           dma_ack=0x%08x\n",
		   i2s_read_reg(dev->i2s_base, DMA_REQ_COUNT),
		   i2s_read_reg(dev->i2s_base, DMA_ACK_COUNT));

	seq_printf(m, "\nclk_ctrl0=0x%08x,         clk_ctrl1=0x%08x\n",
		   i2s_read_reg(dev->i2s_base, I2S_CLK_CTRL0),
		   i2s_read_reg(dev->i2s_base, I2S_CLK_CTRL1));

	return 0;
}

查看i2s设备

一边播放音频 一边cat i2s2就能发现是enable了
但我这里还是没声音。。。

请问你是怎么配置的,外接的也是max98357a吗?
我目前也是没有办法播放,虽然录音功能是正常的。

我照着您的步骤来的,也是无法播放。
但我在tinyplay运行的时候看debug是显示enable的。tinyplay运行完毕也是报同样的错误,没声音

不运行tinyplay的时候也是disable

嗯嗯,我状况也一样,目前还没有解决。
目前情况就是tinyplay可以运行,且运行时i2s是enable的,不运行i2s为disable。
后续如果解决了我再回复你。

diff --git a/linux_5.10/sound/soc/cvitek/cv1835_i2s.c b/linux_5.10/sound/soc/cvitek/cv1835_i2s.c
index 09bd0dc83..b7ab1d221 100644
--- a/linux_5.10/sound/soc/cvitek/cv1835_i2s.c
+++ b/linux_5.10/sound/soc/cvitek/cv1835_i2s.c
@@ -592,8 +592,10 @@ static int cvi_i2s_hw_params(struct snd_pcm_substream *substream,
                        break;
                }
        } else {
-               if ((audio_clk == CVI_24576_MHZ) || (audio_clk == CVI_22579_MHZ))
+               if ((audio_clk == CVI_24576_MHZ) || (audio_clk == CVI_22579_MHZ)) {
                        clk_ctrl1 |= MCLK_DIV(2);
+                       mclk_div = 2;
+               }
                else
                        dev_err(dev->dev, "Get unexpected audio system clk=%d\n", audio_clk);
        }

算能那边你让我这么改,你也试试呢
不过我这暂时还不行