其实底层是调用remap_write()者i2c_transter()来写i2c设备寄存器,自查。
1.Audio Codec查结构体
kernel/include/sound/soc.h
/* SoC Audio Codec device */
<1>.struct snd_soc_codec {
const struct snd_soc_codec_driver *driver;
struct snd_soc_component component;
}
<2>./* codec driver */
struct snd_soc_codec_driver {
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
};
struct snd_soc_component {
struct snd_soc_dai_driver *dai_drv;
const struct snd_soc_component_driver *driver;
int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
struct snd_soc_codec *codec;
struct regmap *regmap;
};
******************************************************************************
1.snd_soc_write()用法代码分析
kernel/sound/soc/soc-io.c
int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val){
return snd_soc_component_write(&codec->component, reg, val);
}
int snd_soc_component_write(struct snd_soc_component *component,unsigned int reg, unsigned int val){
if(component->regmap)
return regmap_write(component->regmap, reg, val);
else if (component->write)
return component->write(component, reg, val);
else
return -EIO;
}
继续往下追,其实底层可以调用remap_write()或者i2c_transter()来写i2c设备.
问题:
调用snd_soc_write()函数后,为什么会调用snd_soc_codec_driver结构体里的write的回调函数?
//1.测试数据
struct snd_soc_codec *codec;
snd_soc_write(codec, 0x08, 0x01);
//2.注册回调函数
static int xxx_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val){
//这里应该是snd_soc_write()传进来的reg = 8,val = 1;
printk(KERN_ERR “%s, %d, reg = %d, val = %d\n", __func__,__LINE__,reg, val);
}
static const struct snd_soc_codec_driver soc_codec_dev_xxx = {
.write = xxx_write,
};
//把soc_codec_dev_xxx放到snd_soc_register_codec()里注册到codec上,其他参数先不管.
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_xxx, xxx, xxx);
//2.分析snd_soc_register_codec()函数
kernel/sound/soc/soc-core.c
int snd_soc_register_codec(struct device *dev, const struct snd_soc_codec_driver *codec_drv,…){
//只看传进来的snd_soc_codec_driver *codec_drv参数。
//这里判断codec_drv->write为真,又注册了一个回调函数,我们看下snd_soc_codec_drv_write()回调函数的实现。
if(codec_drv->write)
codec->component.write = snd_soc_codec_drv_write;
}
//3.snd_soc_codec_drv_write()回调函数的实现
static int snd_soc_codec_drv_write(struct snd_sic_component *component, unsigned int reg, unsigned int val){
//使用snd_soc_codec里的snd_sic_component成员变量,获取snd_soc_codec结构体首地址,snd_soc_component_to_codec通过。使用container_of()函数实现,可以自查.
struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
//snd_soc_codec调用snd_soc_codec_driver结构体的write回调函数,就是调用了上边在soc_codec_dev_xxx里注册的回调函数。
return codec->driver->write(codec, reg, val);
}
*********************************************************************************
4.仿照snd_soc_write()函数写了一个回调demo用法.
#include
/*struct define*/
static struct snd_soc_codec_driver {
int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
};
static struct snd_soc_component {
int (*write)(struct snd_soc_component *com, unsigned int, unsigned int);
};
static struct snd_soc_codec {
struct snd_soc_codec_driver *driver;
struct snd_soc_component component;
};
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct snd_soc_codec *codec = NULL;
//callback实现
int callback_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val){
printf("xxx--->%s(), %d, reg: %d, val: %d\n\n",__FUNCTION__,__LINE__,reg,val);
return 0;
}
static int snd_soc_codec_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val){
struct snd_soc_codec *c_codec = container_of(component, struct snd_soc_codec, component);
printf("xxx--->%s(), %d, reg: %d, val: %d\n",__FUNCTION__,__LINE__,reg,val);
return codec->driver->write(c_codec, reg, val);
}
void codec_register(struct snd_soc_codec_driver *codec_drv){
printf("xxx--->%s(), %d\n",__FUNCTION__,__LINE__);
if(codec_drv->write)
codec->component.write = snd_soc_codec_drv_write;
}
//把snd_soc_write()和callback_write()关联起来;我们调用snd_soc_write就会调用callback_write()函数.
int snd_soc_write(struct snd_soc_codec *codec,unsigned int reg, unsigned int val){
printf("xxx--->%s(), %d, reg: %d, val: %d\n",__FUNCTION__,__LINE__,reg,val);
if(codec->component.write)
return codec->component.write(&codec->component, reg, val);
return 0;
}
int main(){
codec = (struct snd_soc_codec*)malloc(sizeof(struct snd_soc_codec));
//注册回调函数
struct snd_soc_codec_driver test_codec = {
.write = callback_write,
};
codec->driver = &test_codec;
//关联
codec_register(codec->driver);
//方式1:最简单的回调.
//codec->driver->write(codec, 11, 35);
//方式2
while(1){
snd_soc_write(codec, 11, 35);
//最简化
//codec->driver->write(codec, 11, 35);
sleep(1);
}
if(codec)
free(codec);
}