Linux Kernel4.9新增的alsa kcontol宏SND

阅读: 评论:0

Linux Kernel4.9新增的alsa kcontol宏SND

Linux Kernel4.9新增的alsa kcontol宏SND

kcontol为何?写过alsa codec驱动的人都很熟悉了。

droidphone前辈的这篇文章也非常详细:

通俗一点讲,kcontol控件提供了很方便的在线调试手段,比如linux下使用amixer,android下使用timymix,也方便我们封装接口供上层使用,比较静音,设置codec音量等等。通常这些控制都比较简单,基本上就是操作codec寄存器的某一个bit而已,例如TI 5707芯片设置音量和静音的kcontol控制为:

static const struct snd_kcontrol_new tas5707_snd_controls[] = {SOC_SINGLE_TLV("Master Volume", DDX_MASTER_VOLUME, 0,0xff, 1, mvol_tlv),SOC_SINGLE_TLV("Ch1 Volume", DDX_CHANNEL1_VOL, 0,0xff, 1, chvol_tlv),SOC_SINGLE_TLV("Ch2 Volume", DDX_CHANNEL2_VOL, 0,0xff, 1, chvol_tlv),SOC_SINGLE("Ch1 Switch", DDX_SOFT_MUTE, 0, 1, 1),SOC_SINGLE("Ch2 Switch", DDX_SOFT_MUTE, 1, 1, 1),SOC_SINGLE_RANGE("Fine Master Volume", DDX_CHANNEL3_VOL, 0,0x80, 0x83, 0),
};

alsa定义的宏很方便我们对这些寄存器进行操作。在老的kernel版本中,kcontol并没有好的方式处理批量寄存器的设置,比如codec的EQDRC设置,用户层在切换音效时需要设置多组EQ相关的寄存器,这个时候就需要自己想办法实现了,比如增加一个节点等。

最近在看android P的code时发现,最新的linux kernel,增加了SND_SOC_BYTES_EXT这样一个宏,可以设置多组寄存器,先来看看alsa关于这个宏的定义:

#define SND_SOC_BYTES_EXT(xname, xcount, xhandler_get, xhandler_put) 
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_bytes_info_ext, .get = xhandler_get, .put = xhandler_put, .private_value = (unsigned long)&(struct soc_bytes_ext) {.max = xcount} }

xname为控件的名字

xcount为设置寄存器的最大个数

xhandler_get和xhandler_put分别为获取和设置参数的接口,具体的实现由我们来编写

private_value可以作为我们传下来的寄存器值数组

还是拿ti 5707设置EQ参数举例,看看set和get方法的实现:

SND_SOC_BYTES_EXT("EQ table", TAS5707_EQ_LENGTH,tas5707_get_EQ_param, tas5707_set_EQ_param)

 上面是kcontol宏的定义

static int tas5707_set_EQ_param(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol)
{struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);struct snd_soc_codec *codec = snd_soc_component_to_codec(component);struct tas5707_priv *tas5707 = snd_soc_codec_get_drvdata(codec);struct soc_bytes_ext *params = (void *)kcontrol->private_value;void *data;u8 *val, *p = &tas5707_EQ_table[0];unsigned int i = 0, addr;data = kmemdup(ucontrol->value.bytes.data,params->max, GFP_KERNEL | GFP_DMA);if (!data)return -ENOMEM;val = (u8 *)data;memcpy(p, val, params->max / sizeof(u8));for (i = 0; i < 14; i++) {addr = DDX_CH1_BQ_0 + i;regmap_raw_write(tas5707->regmap,addr, p, TAS5707_EQ_PARAM_LENGTH);p += TAS5707_EQ_PARAM_LENGTH;}kfree(data);return 0;
}static int tas5707_get_EQ_param(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol)
{/*struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);*struct snd_soc_codec *codec = snd_soc_component_to_codec(component);*struct tas5707_priv *tas5707 = snd_soc_codec_get_drvdata(codec);*/unsigned int i, addr;u8 *val = (u8 *)ucontrol->value.bytes.data;u8 *p = &tas5707_EQ_table[0];for (i = 0; i < 14; i++) {addr = DDX_CH1_BQ_0 + i;/*regmap_raw_read(tas5707->regmap,*  addr, p, TAS5707_EQ_PARAM_LENGTH);*/memcpy(val, p, TAS5707_EQ_PARAM_LENGTH);p += TAS5707_EQ_PARAM_LENGTH;val += TAS5707_EQ_PARAM_LENGTH;}return 0;
}

写完了kernel的kcontol接口,即通过tinyalsa封装接口往kernel传递

 

本文发布于:2024-02-02 23:16:16,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170688697547097.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Linux   alsa   SND   kcontol
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23