ALSA駆動中snd_soc_write()原理分析及びdemo


       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
", __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

",__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
",__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
",__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
",__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); }