I2C之snd_soc_write()/i2c_transfer()/regmap_write()区别




一.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)){
  	   
}











猜你喜欢

转载自blog.csdn.net/u010164190/article/details/124825487
I2C
今日推荐