Alsa或TinyAlsa添加控制接口

image

背景

  • Platform: RK3399
  • Kernel: v4.4.10

项目需要添加一个控制外部电路Mute的接口,主要是控制一个GPIO

过程

DTS配置

添加GPIO配置
类似:

1
2
3
4
5
6
7
8
9
10
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>;
}
...
}

驱动源码添加

  1. 在驱动probe函数中获取gpio相关信息:
    xxx->amp_gpio = of_get_named_gpio(np, "amp-gpios", 0);

    1
    2
    3
    4
    5
    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;
    }
  2. snd_kcontrol_new中添加dapm kcontrol:

    1
    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

  3. 添加对应的xhandler_getxhandler_put函数,来控制对应的GPIO
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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;
    }

这样就可以通过标准的alsa接口去控制了,如TinymixAlsamix
用户空间调用kcontrol:snd_ctl_ioctl
添加其他的控制类似

kcontrol通常用于控件的音量等控制,而dapm kcontrol相关的kcontrol则是用于widget电源管理的开关

参考及扩展

  1. Asoc dapm(一) - kcontrol
Donate comment here