【RK3568调试记】给RK809添加音量调节功能

最近在搞一个RK3568的项目,用到了codec的录音放音功能。使用aplay来播放wav,差点把我耳朵震聋。于是我打算使用alsamixer来调小音量,结果给我整了这么一出:
在这里插入图片描述
没有音量条也就无法调节音量,使用amixer命令看一下:
在这里插入图片描述
仅有两个控件,而这两个控件也不是调音量的,难道说RK3568的codec不支持音量调节吗?
RK3568使用的codec芯片是rk809,同时也是PMIC(就很神奇)。带着问题百度了下,发现可以通过修改设备树来调节音量:

rk809_codec: codec {
			#sound-dai-cells = <0>;
			compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
			clocks = <&cru I2S1_MCLKOUT>;
			clock-names = "mclk";
			assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
			assigned-clock-rates = <12288000>;
			assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;
			pinctrl-names = "default";
			pinctrl-0 = <&i2s1m0_mclk>;
			hp-volume = <20>;  //此处修改耳机音量,3~255即1.125db~-95db,0.375db/step
			spk-volume = <3>;  //此处修改喇叭音量,3~255即1.125db~-95db,0.375db/step
			mic-in-differential;
			status = "okay";
		};

修改后再播放果然生效,证明rk809是具备调节音量的功能的。

但问题还是没有解决,总不能听个音乐想调下音量,于是修改设备树,重新编译,烧写到产品中…正确的做法是把音量调节控件添加到codec驱动中使其支持音量调节功能。

根据设备树rk809的compatible属性找到它的驱动源码sound/soc/codecs/rk817_codec.c。找到它的控件注册位置:

static int rk817_probe(struct snd_soc_component *component)
{
	/* 省略 */
	snd_soc_add_component_controls(component, rk817_snd_path_controls,
				       ARRAY_SIZE(rk817_snd_path_controls));
	return 0;
}

rk817_snd_path_controls就是控件对象了,它的定义也在本文件中:

static struct snd_kcontrol_new rk817_snd_path_controls[] = {
	SOC_ENUM_EXT("Playback Path", rk817_playback_path_type,
		     rk817_playback_path_get, rk817_playback_path_put),

	SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type,
		     rk817_capture_path_get, rk817_capture_path_put),
};

这两个控件与amixer命令查找出了两个控件相吻合。需要添加第三个控件用于音量调节。

这里我的做法是参考一个比较熟悉的codec的驱动wm8960(sound/soc/codecs/wm8960.c),它是这样添加音量调节控件的:
在这里插入图片描述
这个宏的原型:

include/sound/soc.h
SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array)
参数:
xname: 控件件名称,
reg_left: 左声道寄存器地址
reg_right: 右声道寄存器地址
xshift: 控件功能在寄存器中需要修改第几个bit
xmax: 寄存器可写入的最大值
xinvert: 写入寄存器的值是否需要反转(0:0就是0; 1:0为xmax-0)
tlv_array: 控制元数据(就是一个容器),alsa以此来定义dB范围/比例

宏展开SOC_DOUBLE_R_TLV(“Playback Volume”, WM8960_LDAC, WM8960_RDAC,
0, 255, 0, dac_tlv),

SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, 0, 255, 0, dac_tlv),
{
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = ("Playback Volume"),
	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.tlv.p = (dac_tlv),  //控制元数据
	.info = snd_soc_info_volsw,
	.get = snd_soc_get_volsw,  //amixer的sget或cget的回调
	.put = snd_soc_put_volsw,  //amixer的sset或cset的回调
	.private_value = SOC_DOUBLE_R_VALUE( WM8960_LDAC,   WM8960_RDAC,             0,        255,                0)
  //.private_value = SOC_DOUBLE_R_VALUE(左声道音量reg,  右声道音量reg, 寄存器位offset, 寄存器最大值, 设置的值是否反转)
},

再看它的元数据dac_tlv的定义:

static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
dac_tlv: 元数据变量
-12750: 最小增益(单位0.01dB),即最小音量为-127.5dB,需要参考codec datasheet
50: 调节音量的步长(单位0.01dB),0.5dB 0~255-127.5dB~0dB,127.5/256约为0.5
1: 音量最小是是否需要静音(0:; 1: 是)

rk809的道理基本一样,只是需要确定音量调节的寄存器地址,查看rk809的datasheet:
在这里插入图片描述
二者在sound/soc/codecs/rk817_codec.h中有定义:

#define RK817_CODEC_DDAC_VOLL		(RK817_CODEC_BASE + 0x31)
#define RK817_CODEC_DDAC_VOLR		(RK817_CODEC_BASE + 0x32)

最后照猫画虎,添加音量调节控件:

#include <sound/tlv.h>  //+ 头文件。否则编译找不到宏DECLARE_TLV_DB_SCALE
/* 省略 */
static const DECLARE_TLV_DB_SCALE(dac_tlv, -9500, 37, 1);  //+ 音量调节控件元数据,根据rk809datasheet -1.125db~-95db,0.375db/step

static struct snd_kcontrol_new rk817_snd_path_controls[] = {
	SOC_ENUM_EXT("Playback Path", rk817_playback_path_type,
		     rk817_playback_path_get, rk817_playback_path_put),

	SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type,
		     rk817_capture_path_get, rk817_capture_path_put),
	
	SOC_DOUBLE_R_TLV("Playback Volume", RK817_CODEC_DDAC_VOLL,  RK817_CODEC_DDAC_VOLR,
		 0, 255, 0, dac_tlv),  //+ 音量调节控件
};

编译烧写内核,alsamixer成功出现音量条:
在这里插入图片描述
amixer查看,出现音量控件’Playback’:
在这里插入图片描述
使用amixer contents查看详情:
在这里插入图片描述
分别用amixer sset Playback 0,0以及amixer sset Playback 255,255测试最大和最小音量:
在这里插入图片描述
然后使用aplay放歌出现了一个小bug,使用amixer sset Playback 0,0原本表示静音却放出了最大音量,而amixer sset Playback 255,255是最小音量,这与标定值相反。控件的配置是照搬wm8960的,对比wm8960和rk809的datasheet得到答案:
rk809:
在这里插入图片描述
wm8960:
在这里插入图片描述
wm8960音量与寄存器值对应关系为255对应最大值0dB,而rk809 255对应最小值-95dB,正好相反!因此需要修改控件参数:

static struct snd_kcontrol_new rk817_snd_path_controls[] = {
	SOC_ENUM_EXT("Playback Path", rk817_playback_path_type,
		     rk817_playback_path_get, rk817_playback_path_put),

	SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type,
		     rk817_capture_path_get, rk817_capture_path_put),
	
	SOC_DOUBLE_R_TLV("Playback Volume", RK817_CODEC_DDAC_VOLL,  RK817_CODEC_DDAC_VOLR,
		 0, 255, 1/*这里把0修改为1,表示寄存器写入x,实际值为255-x*/, dac_tlv),
};

成功修复bug!

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
RK3568是Rockchip公司生产的一款高性能处理器,它集成了多个功能模块,其中包括SATA接口,用于连接硬盘或固态硬盘。调试SATA时,可以按照以下步骤进行: 1. 硬件连接:首先,将SATA数据线和电源线正确连接到RK3568处理器和硬盘上。确保连接稳固,避免松动或接触不良。 2. 软件设置:在开始调试之前,需要通过系统设置对SATA功能进行配置。进入系统设置菜单,找到SATA选项,检查并启用SATA功能。确保设置与硬件连接方式和硬盘类型相匹配。 3. 设备检测:接下来,打开系统设备管理器,查看是否成功检测到连接的SATA设备。如果设备未显示或出现异常,可能是硬件连接有问题或设备驱动程序未正确安装。这时需要重新检查硬件连接,并安装或更新正确的驱动程序。 4. 参数配置:一旦SATA设备被检测到并正常工作,可以进入设备管理器或系统设置来配置相关参数,如传输速率、缓存模式等。根据硬盘规格和需求,进行适当的调整。 5. 功能测试:完成参数配置后,可进行一些SATA功能测试,如读写速度测试、文件传输测试等,以验证硬盘与处理器的通信和性能。如果测试结果不理想,可能需要重新检查硬件连接、参数配置或进行故障排除。 6. 调试优化:如果在调试过程中遇到性能问题或其他异常情况,可以通过调整部分参数或使用专用调试工具来进行优化。比如,可以尝试使用SATA调试工具软件来监测IO性能、故障日志等,以定位和解决问题。 总结:调试SATA需要确保正确的硬件连接和软件设置,检测设备是否成功连接并配置相关参数,进行功能测试和优化,以保证SATA设备与RK3568处理器正常工作,达到预期的功能和性能。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值