一.snd_soc_write()流程
1.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>.
snd soc component
struct snd_soc_component {
struct snd_soc_card *card;
int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);
int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
struct regmap *regmap;
};
//soc codec driver
struct snd_soc_codec_driver {
/* codec IO */
struct regmap *(*get_regmap)(struct device *);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
};
<3>.struct regmap {
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
int (*reg_update_bits)(void *context, unsigned int reg,unsigned int mask, unsigned int val);
};
2.sound/soc/soc-io.c
<1>.int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,unsigned int val){
return snd_soc_component_write(&codec->component, reg, val);
}
<2>.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);
}
3.component->write()流程//主线一:
//kernel/sound/soc/soc-core.c
<1>.int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv,
int num_dai){
if (codec_drv->write)
codec->component.write = snd_soc_codec_drv_write;
}
<2>.static int snd_soc_codec_drv_write(struct snd_soc_component *component,unsigned int reg, unsigned int val){
struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
return codec->driver->write(codec, reg, val);//asoc core代码调用到codec的driver侧,找到结构体线索:snd_soc_codec{};--->snd_soc_codec_driver{};--->int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
}
//kernel/sound/soc/codecs/cx20442.c
<3>.static const struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
.set_bias_level = cx20442_set_bias_level,
.reg_cache_default = &cx20442_reg,
.reg_cache_size = 1,
.reg_word_size = sizeof(u8),
.read = cx20442_read_reg_cache,
.write = cx20442_write,//对audio codec操作的回调函数
.component_driver = {
.dapm_widgets = cx20442_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets),
.dapm_routes = cx20442_audio_map,
.num_dapm_routes = ARRAY_SIZE(cx20442_audio_map),
},
};
<4>.static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,unsigned int value){
struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
u8 *reg_cache = codec->reg_cache;
int vls, vsp, old, len;
char buf[18];
//写到audio codec寄存器
codec->hw_write(cx20442->control_data, buf, len);
}
<5>.static void v253_receive(struct tty_struct *tty,const unsigned char *cp, char *fp, int count){
struct snd_soc_codec *codec = tty->disc_data;
struct cx20442_priv *cx20442;
codec->hw_write = (hw_write_t)tty->ops->write;
}
<6>.static int v253_open(struct tty_struct *tty){
tty->ops->write(tty, v253_init, len);//命令通过tty串口设备发送
}
//kernel/drivers/tty/tty_io.c
<7>.static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,//
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
.show_fdinfo = tty_show_fdinfo,
};
<8>.static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos){
ret = do_tty_write(ld->ops->write, tty, file, buf, count);
}
<9>.static inline ssize_t do_tty_write(ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
struct tty_struct *tty,
struct file *file,
ret = write(tty, file, tty->write_buf, size);
}
struct tty_operations {
int (*write)(struct tty_struct * tty, const unsigned char *buf, int count);
};
//drivers/misc/pti
static const struct tty_operations pti_tty_driver_ops = {
.open = pti_tty_driver_open,
.close = pti_tty_driver_close,
.write = pti_tty_driver_write,
.write_room = pti_tty_write_room,
.install = pti_tty_install,
.cleanup = pti_tty_cleanup
};
<10>.static int pti_tty_driver_write(struct tty_struct *tty, const unsigned char *buf, int len){
pti_write_to_aperture(pti_tty_data->mc, (u8 *)buf, len);
}
<11>.static void pti_write_to_aperture(struct pti_masterchannel *mc, u8 *buf,int len){
iowrite32(ptiword, aperture);
}
//arch/arm/mach-ixp4xx/include/mach/io.h
#define iowrite32(v, p) iowrite32(v, p)
<11>.static inline void iowrite32(u32 value, void __iomem *addr){
#ifndef CONFIG_IXP4XX_INDIRECT_PCI
__raw_writel((u32 __force)cpu_to_le32(value), addr);
#else
__indirect_writel(value, addr);
#endif
}
二、regmap_write()流程
1.kernel/drivers/i2c/i2c-core-base.c
<2>.int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num){
ret = __i2c_transfer(adap, msgs, num);
}
<2>.int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num){
ret = adap->algo->master_xfer(adap, msgs, num);
}
2.kernel/drivers/i2c/busses/i2c-sprd.c
<1>.static const struct i2c_algorithm sprd_i2c_algo = {
.master_xfer = sprd_i2c_master_xfer,
.functionality = sprd_i2c_func,
};
<2>.static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,struct i2c_msg *msgs, int num){
ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im++], 1);
}
<3>.static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap,struct i2c_msg *msg, bool is_last_msg){
sprd_i2c_data_transfer(i2c_dev);
}
<4>.static void sprd_i2c_data_transfer(struct sprd_i2c *i2c_dev){
sprd_i2c_write_bytes(i2c_dev, i2c_dev->buf, need_tran);
}
<5>.static void sprd_i2c_write_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len){
writeb(buf[i], i2c_dev->base + I2C_TX);
}
<6>.kernel/arch/alpha/kernel/io.c
void writeb(u8 b, volatile void __iomem *addr){
__raw_writeb(b, addr);
}
三、i2c_transfer()流程
1.kernel/drivers/base/regmap/regmap.c
<1>.int regmap_write(struct regmap *map, unsigned int reg, unsigned int val){
ret = _regmap_write(map, reg, val);
}
<2>.int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val){
ret = regcache_write(map, reg, val);
}
2.kernel/drivers/base/regmap/regcache.c
struct regmap {
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
int (*reg_update_bits)(void *context, unsigned int reg,unsigned int mask, unsigned int val);
const struct regcache_ops *cache_ops;
};
struct regcache_ops {
int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
};
<1>.int regcache_write(struct regmap *map,unsigned int reg, unsigned int value){
map->cache_ops->write(map, reg, value)
}
3.kernel/drivers/base/regmap/regcache-rbtree.c
struct regcache_ops regcache_rbtree_ops = {
.read = regcache_rbtree_read,
.write = regcache_rbtree_write,
.sync = regcache_rbtree_sync,
.drop = regcache_rbtree_drop,
};
<1>.static int regcache_rbtree_write(struct regmap *map, unsigned int reg, unsigned int value){
regcache_rbtree_set_register(map, rbnode,reg - rbnode->base_reg, value);
regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
}
4.kernel/lib/rbtree.c
<1>.void rb_insert_color(struct rb_node *node, struct rb_root *root){
__rb_insert(node, root, false, NULL, dummy_rotate);//红黑树插入
}
EXPORT_SYMBOL(rb_insert_color);
<2>.static __always_inline void __rb_insert(struct rb_node *node, struct rb_root *root, bool newleft, struct rb_node **leftmost,
void (*augment_rotate)(struct rb_node *old, struct rb_node *new)){
}
I2C之snd_soc_write()/i2c_transfer()/regmap_write()区别
猜你喜欢
转载自blog.csdn.net/u010164190/article/details/124825487
今日推荐
周排行