Linux Kernel4.9新增的alsa kcontol宏SND_SOC_BYTES_EXT

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

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

https://blog.csdn.net/droidphone/article/details/12793293

通俗一点讲,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的EQ\DRC设置,用户层在切换音效时需要设置多组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传递

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分析 x Symbol: SND_SOC_ROCKCHIP_I2S [=n] x x Type : tristate x x Prompt: Rockchip I2S Device Driver x x Location: x x -> Device Drivers x x -> Sound card support (SOUND [=y]) x x -> Advanced Linux Sound Architecture (SND [=y]) x x (6) -> ALSA for SoC audio support (SND_SOC [=y]) x x -> ASoC support for Rockchip (SND_SOC_ROCKCHIP [=n]) x x Defined at sound/soc/rockchip/Kconfig:18 x x Depends on: SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && CLKDEV_LOOKUP [=y] && SND_SOC_ROCKCHIP [=n] x x Selects: SND_SOC_GENERIC_DMAENGINE_PCM [=n] x x Selected by [n]: x x - SND_SOC_ROCKCHIP_MAX98090 [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] x x - SND_SOC_ROCKCHIP_RT5645 [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] x x - SND_SOC_ROCKCHIP_RT5651 [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] x x - SND_SOC_ROCKCHIP_RT5651_RK628 [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] x x - SND_SOC_RK3288_HDMI_ANALOG [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] x x - SND_SOC_RK3399_GRU_SOUND [=n] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SND_SOC_ROCKCHIP [=n] && I2C [=y] && GPIOLIB [=y] && CLKDEV_LOOKUP [=y] && SPI [=y] x
最新发布
07-20

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值