Alsa或TinyAlsa添加控制接口
背景
- Platform: RK3399
- Kernel: v4.4.10
项目需要添加一个控制外部电路Mute的接口,主要是控制一个GPIO
过程
DTS配置
添加GPIO配置
类似:
amp-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
...
&pinctrl {
...
xxx_gpios: xxx-gpios {
rockchip,pins = <3 16 RK_FUNC_GPIO &pcfg_pull_none>,
<1 17 RK_FUNC_GPIO &pcfg_pull_none>;
}
...
}
驱动源码添加
- 在驱动
probe
函数中获取gpio相关信息:
xxx->amp_gpio = of_get_named_gpio(np, "amp-gpios", 0);
if (gpio_is_valid(xxx->amp_gpio)) { ret = devm_gpio_request_one(&i2c->dev, xxx->amp_gpio,GPIOF_OUT_INIT_LOW, "xxx amp ctl"); if (ret != 0) return ret; }
- 在
snd_kcontrol_new
中添加dapm kcontrol
:
相关SOC_SINGLE_BOOL_EXT("Local AMP Hw Mute", 1, local_amp_hw_mute_get, local_amp_hw_mute_put),
dapm kcontrol
定义可查看文件:kernel/include/sound/soc.h
- 添加对应的
xhandler_get
和xhandler_put
函数,来控制对应的GPIO
这样就可以通过标准的alsa接口去控制了,如static int local_amp_hw_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct xxx_priv *xxx = snd_soc_codec_get_drvdata(codec); ucontrol->value.integer.value[0] = xxx->amp_mute_en; return 0; } static int local_amp_hw_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct xxx_priv *xxx = snd_soc_codec_get_drvdata(codec); unsigned int val = ucontrol->value.integer.value[0]; if (val > 1) return -EINVAL; mutex_lock(&xxx->lock); xxx->amp_mute_en = val; if (gpio_is_valid(xxx->amp_gpio)) { gpio_set_value(xxx->amp_gpio, 1-val); } mutex_unlock(&xxx->lock); return 0; }
Tinymix
或Alsamix
用户空间调用kcontrol:snd_ctl_ioctl
添加其他的控制类似kcontrol通常用于控件的音量等控制,而dapm kcontrol相关的kcontrol则是用于widget电源管理的开关
参考及扩展
评论