ALSA声卡12_从零编写之添加音量控制_学习笔记

发布时间:2024-07-16  

1、设置音量时应用程序的调用过程

(1)strace分析: amixer cset numid=1 30 (设置音量)
/dev/snd/controlC0
open
SNDRV_CTL_IOCTL_CARD_INFO
SNDRV_CTL_IOCTL_PVERSION
SNDRV_CTL_IOCTL_ELEM_INFO
SNDRV_CTL_IOCTL_ELEM_READ
SNDRV_CTL_IOCTL_ELEM_WRITE : snd_ctl_elem_write_user

(2)应用程序调用SNDRV_CTL_IOCTL_ELEM_WRITE时,驱动程序调用snd_ctl_elem_write_user函数,这个函数从用户空间把一些参数拷贝进来,然后调用函数snd_ctl_elem_write

(3)函数snd_ctl_elem_write

找到一个snd_kcontrol结构体,然后调用snd_control结构体的put函数。


(4)这个snd_kcontrol结构体是谁提供的

ASOC驱动程序分为3大块(machine,codec,platform),应该在codec这一块来提供的,因为它跟声卡密切相关。去调节音量的时候肯定要调整它



2、写程序(uda1341.c(codec))

(1)结构体snd_kcontrol_new

static const struct snd_kcontrol_new uda1341_vol_control = 
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, //表示snd_kcontrol结构体用于哪一类设备(表示进行参数设置)
    .name = "Master Playback Volume",  //音量控制,每个声卡驱动程序的snd_kcontrol各不相同,为什么应用程序都可以调整它的音量,对于某些常用的属性,它们都有固定的名字。应用程序根据名字找到它的snd_kcontrol项,调用里面的put函数。
.info = uda1341_info_vol,  //获得一些信息,如音量范围是多少
.get  = uda1341_get_vol,//获得当前的音量值
.put  = uda1341_put_vol, //设置音量
};


(2) 获得音量信息,比如最小值最大值

/*
 * 获得音量信息,比如最小值最大值
 */
int uda1341_info_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;//音量值的类型是整数
uinfo->count = 2;//声道数是双声道的
uinfo->value.integer.min = 0;//最小整数,
uinfo->value.integer.max = 63;//最大整数,
return 0;
}

因为uda1341的音量控制是6位的(0表示最大音量,63表示最小音量),而应用程序中0表示最小音量,值越大表示音量越大


(3)获得当前音量值

/*
 * 获得当前音量值
 */
int uda1341_get_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);


    ucontrol->value.integer.value[1] =  //这里   表示ucontrol->value.integer.value[0] 等于ucontrol->value.integer.value[1] ,因为是双声道
ucontrol->value.integer.value[0] = 63 - snd_soc_read(codec, UDA1341_DATA00);//读寄存器DAT00的值,因为驱动程序的值和应用程序的值大小是相反的,uda1341不支持寄存器的读操作,要想得到一个寄存器的值,是去读某个cache(这个cache保存的是设置寄存器的值)
return 0;
}

(4) 设置当前音量值

/*
 * 设置当前音量值
 */
int uda1341_put_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int val;


val = 63 - ucontrol->value.integer.value[0];//应用程序传进来的值写到寄存器里面要反转


    snd_soc_write(codec, UDA1341_DATA00, val);//把值val写到寄存器DATA00中去
    
return 0;
}

3、结构体snd_kcontrol_new和内核部分的连接

(1)probe函数

static int uda1341_soc_probe(struct snd_soc_codec *codec)
{
    int ret;
    uda1341_init_regs(codec);
    
ret = snd_soc_add_codec_controls(codec, &uda1341_vol_control, 1);
    return ret;
}


4、测试


amixer  controls查看控制项

amixer cget numid=1表示查看当前音量

amixer cset numid=1 30设置音量



5、Input Mux

因为不同的板子的麦克风通道不同(在uda1341),用同一驱动,想录音时应用程序应该设置input mux选项。



表明它能选择哪个麦克风通道,当前是哪一个麦克风通道,设置哪一个麦克风通道


值uda134x_mixer_enum[2]是数组的第2项


6、

让板子使用内核自带的驱动程序


查看设备节点和控制项(input mux在倒数第二项)


查看控制项第11项的值(当前值是0)


若选择第1个通道(模拟通道)最后1个参数表明第几个通道


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>