ALSA声卡12_从零编写之添加音量控制_学习笔记
1、設(shè)置音量時(shí)應(yīng)用程序的調(diào)用過程
(1)strace分析: amixer cset numid=1 30?(設(shè)置音量)
/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)應(yīng)用程序調(diào)用SNDRV_CTL_IOCTL_ELEM_WRITE時(shí),驅(qū)動(dòng)程序調(diào)用snd_ctl_elem_write_user函數(shù),這個(gè)函數(shù)從用戶空間把一些參數(shù)拷貝進(jìn)來,然后調(diào)用函數(shù)snd_ctl_elem_write
(3)函數(shù)snd_ctl_elem_write
找到一個(gè)snd_kcontrol結(jié)構(gòu)體,然后調(diào)用snd_control結(jié)構(gòu)體的put函數(shù)。
(4)這個(gè)snd_kcontrol結(jié)構(gòu)體是誰提供的
ASOC驅(qū)動(dòng)程序分為3大塊(machine,codec,platform),應(yīng)該在codec這一塊來提供的,因?yàn)樗暱芮邢嚓P(guān)。去調(diào)節(jié)音量的時(shí)候肯定要調(diào)整它
2、寫程序(uda1341.c(codec))
(1)結(jié)構(gòu)體snd_kcontrol_new
static const struct?snd_kcontrol_new?uda1341_vol_control =?
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,?//表示snd_kcontrol結(jié)構(gòu)體用于哪一類設(shè)備(表示進(jìn)行參數(shù)設(shè)置)
? ? .name = "Master Playback Volume", ?//音量控制,每個(gè)聲卡驅(qū)動(dòng)程序的snd_kcontrol各不相同,為什么應(yīng)用程序都可以調(diào)整它的音量,對(duì)于某些常用的屬性,它們都有固定的名字。應(yīng)用程序根據(jù)名字找到它的snd_kcontrol項(xiàng),調(diào)用里面的put函數(shù)。
.info = uda1341_info_vol, ?//獲得一些信息,如音量范圍是多少
.get ?= uda1341_get_vol,//獲得當(dāng)前的音量值
.put ?= uda1341_put_vol,?//設(shè)置音量
};
(2)?獲得音量信息,比如最小值最大值
/*
?* 獲得音量信息,比如最小值最大值
?*/
int uda1341_info_vol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;//音量值的類型是整數(shù)
uinfo->count = 2;//聲道數(shù)是雙聲道的
uinfo->value.integer.min = 0;//最小整數(shù),
uinfo->value.integer.max = 63;//最大整數(shù),
return 0;
}
因?yàn)閡da1341的音量控制是6位的(0表示最大音量,63表示最小音量),而應(yīng)用程序中0表示最小音量,值越大表示音量越大
(3)獲得當(dāng)前音量值
/*
?* 獲得當(dāng)前音量值
?*/
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] ,因?yàn)槭请p聲道
ucontrol->value.integer.value[0] = 63 - snd_soc_read(codec, UDA1341_DATA00);//讀寄存器DAT00的值,因?yàn)轵?qū)動(dòng)程序的值和應(yīng)用程序的值大小是相反的,uda1341不支持寄存器的讀操作,要想得到一個(gè)寄存器的值,是去讀某個(gè)cache(這個(gè)cache保存的是設(shè)置寄存器的值)
return 0;
}
(4)?設(shè)置當(dāng)前音量值
/*
?* 設(shè)置當(dāng)前音量值
?*/
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];//應(yīng)用程序傳進(jìn)來的值寫到寄存器里面要反轉(zhuǎn)
? ? snd_soc_write(codec, UDA1341_DATA00, val);//把值val寫到寄存器DATA00中去
? ??
return 0;
}
3、結(jié)構(gòu)體snd_kcontrol_new和內(nèi)核部分的連接
(1)probe函數(shù)
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、測(cè)試
amixer ?controls查看控制項(xiàng)
amixer cget numid=1表示查看當(dāng)前音量
amixer cset numid=1 30設(shè)置音量
5、Input Mux
因?yàn)椴煌陌遄拥柠溈孙L(fēng)通道不同(在uda1341),用同一驅(qū)動(dòng),想錄音時(shí)應(yīng)用程序應(yīng)該設(shè)置input mux選項(xiàng)。
表明它能選擇哪個(gè)麥克風(fēng)通道,當(dāng)前是哪一個(gè)麥克風(fēng)通道,設(shè)置哪一個(gè)麥克風(fēng)通道
值uda134x_mixer_enum[2]是數(shù)組的第2項(xiàng)
6、
讓板子使用內(nèi)核自帶的驅(qū)動(dòng)程序
查看設(shè)備節(jié)點(diǎn)和控制項(xiàng)(input mux在倒數(shù)第二項(xiàng))
查看控制項(xiàng)第11項(xiàng)的值(當(dāng)前值是0)
若選擇第1個(gè)通道(模擬通道)最后1個(gè)參數(shù)表明第幾個(gè)通道
轉(zhuǎn)載于:https://www.cnblogs.com/alan666/p/8311864.html
總結(jié)
以上是生活随笔為你收集整理的ALSA声卡12_从零编写之添加音量控制_学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux内核移植imx8,NXP iM
- 下一篇: Hadoop之Hbase安装和配置