Es8323.c (sound\soc\codecs) 

1.入口函数

dts里面

status = "okay";
        es8323: es8323@11 {
                status = "okay";
es8323";
                reg = <0x11>;
                pa-en1 = <&gpio1 GPIO_A0 GPIO_ACTIVE_HIGH>;
                pa-en2 = <&gpio1 GPIO_A1 GPIO_ACTIVE_HIGH>;
        };

static const struct i2c_device_id es8323_i2c_id[] = {
es8323", 0 },{ }};
static struct i2c_driver es8323_i2c_driver = {
 .driver = {
  .name = "ES8323",
  .owner = THIS_MODULE,
 },
 .shutdown = es8323_i2c_shutdown,
 .probe = es8323_i2c_probe,
 .remove = es8323_i2c_remove,
 .id_table = es8323_i2c_id,
};

匹配之后就进入probe函数
I2C适配器的能力的相关代码
/* declare our i2c functionality */
static u32 rockchip_i2c_func(struct i2c_adapter *adap)
{
I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
}
/* i2c bus registration info */
static const struct i2c_algorithm rockchip_i2c_algorithm = {
        .master_xfer            = rockchip_i2c_xfer,
rockchip_i2c_func,
};

es8323_i2c_probe
//分配es8323_priv结构体
 //用来判定设配器的能力,这一点非常重要。你也可以直接查看对应适配器的能力,开头有相关函数声明
    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) 
 //设置控制接口
pa-en1", 0, &flags); //获取dts的相关控制脚
//获取默认状态
 //一般gpio_request封装了mem_request(),起保护作用,最后要调用mem_free之类的。主要是告诉内核这地址被占用了。当其它地方调用同一地址的gpio_request就会报告错误,该地址已被申请。在/proc/mem应该会有地址占用表描述。
        ret = gpio_request(es8323->spk_ctl_gpio, NULL); 
 //设置状态
 。。。。获取另外两个端口。。。。
    ret =  snd_soc_register_codec(&i2c->dev, &soc_codec_dev_es8323, &es8323_dai, 1); //注册codec,单独分析


2.注册codec,单独分析
codec相关结构体,主要是codec的相关操作函数
static struct snd_soc_codec_driver soc_codec_dev_es8323 = {
 .probe =	es8323_probe,
 .remove =	es8323_remove,
 .suspend =	es8323_suspend,
 .resume =	es8323_resume,
 .set_bias_level = es8323_set_bias_level,
 .reg_cache_size = ARRAY_SIZE(es8323_reg),
 .reg_word_size = sizeof(u16),
 .reg_cache_default = es8323_reg,
 .reg_cache_step = 1,
}

codec dai相关的函数
static struct snd_soc_dai_ops es8323_ops = {
 .startup = es8323_pcm_startup,
 .hw_params = es8323_pcm_hw_params,
 .set_fmt = es8323_set_dai_fmt,
 .set_sysclk = es8323_set_dai_sysclk,
 .digital_mute = es8323_mute,
};
static struct snd_soc_dai_driver es8323_dai = {
 .name = "ES8323 HiFi",
 .playback = {
  .stream_name = "Playback",
  .channels_min = 1,
  .channels_max = 2,
  .rates = es8323_RATES,// SNDRV_PCM_RATE_48000,
  .formats = es8323_FORMATS,
 },
 .capture = {
  .stream_name = "Capture",
  .channels_min = 1,
  .channels_max = 8,
  .rates = es8323_RATES,// SNDRV_PCM_RATE_48000,
  .formats = es8323_FORMATS,
  },
es8323_ops,
 .symmetric_rates = 1,
};

函数分析
snd_soc_register_codec(&i2c->dev, &soc_codec_dev_es8323, &es8323_dai, 1);
 //分配snd_soc_codec结构体
  /* create CODEC component name */
    codec->name = fmt_single_name(dev, &codec->id); //通过一定规则获取名字
//因为没有指定,所有默认是这个模式
//这里没有
//这里没有
//这里没有
 //这里没有
//这里没有
//这里没有
    codec->dapm.bias_level = SND_SOC_BIAS_OFF;
    codec->dapm.dev = dev;
     codec->dapm.codec = codec;
//这里没有
//这里没有
    codec->dev = dev;
    codec->driver = codec_drv;
//这里是1
  /* allocate CODEC register cache */
    if (codec_drv->reg_cache_size && codec_drv->reg_word_size)
   //reg_cache_size这里是52个,word是2 byte,reg_size =52*2=104
        reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
        codec->reg_size = reg_size; //104
 /* it is necessary to make a copy of the default register cache
        * because in the case of using a compression type that requires
        * the default register cache to be marked as the
        * kernel might have freed the array by the time we initialize the cache. */
        有必要复制默认寄存器缓存的副本,因为在需要使用压缩类型的情况下,在初始化缓存时,内核可能释放了数组,需要默认的寄存器缓存被标记
        if (codec_drv->reg_cache_default) //一组默认寄存器
 在kernel中可以通过kmemdup将一种类型的数据赋值给另外同一个类型的数据,把reg_cache_default赋值给reg_def_copy 
reg_size, GFP_KERNEL);
//我们这里没有
//这里num_dai=1
  //让DAI的数据格式同时拥有大小字节序
        fixup_codec_formats(&dai_drv[i].playback);
 //比如SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
        fixup_codec_formats(&dai_drv[i].capture);
 list_add(&codec->list, &codec_list); //把codec->list加到codec_list的最前面
  /* register any DAIs */
//注册dai
 //这里count=1
 //分配struct snd_soc_dai *dai;
        /* create DAI component name */
        dai->name = fmt_multiple_name(dev, &dai_drv[i]); //这里名字是ES8323 HiFi

        dai->driver = &dai_drv[i];
        dai->dapm.dev = dev;
//从codec_list找出对应的codec

 //赋值
 list_add(&dai->list, &dai_list); //把dai->list加入到dai_list头部


3.es8323_probe
 //es8323 register cache函数,cache是一个数组
    codec->write = es8323_write;
        ret = codec->hw_write(codec->control_data, data, 2);
  //issue a single I2C message in master transmit mode
 //i2c的写函数
//得到i2c_client
    es8323_codec = codec;
//写寄存器复位
        snd_soc_write(codec, ES8323_CONTROL1, 0x80);
        return snd_soc_write(codec, ES8323_CONTROL1, 0x00);
    .........
//一些初始化寄存器设置
    .............
//设置偏压为待机



4.es8323_set_dai_sysclk
/* The set of rates we can generate from the above for each SYSCLK */
static unsigned int rates_12288[] = {
 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
};
static struct snd_pcm_hw_constraint_list constraints_12288 = {
 .count	= ARRAY_SIZE(rates_12288),
 .list	= rates_12288,
};

 //我们这里设置12288000 
    case 12288000:
constraints_12288; //我们可以从上面为每一个SYSCLK生成一组速率
        es8323->sysclk = freq;


5.es8323_pcm_hw_params //caodec的硬件参数设置
/* codec hifi mclk clock divider coefficients */
static const struct _coeff_div coeff_div[] = {
 /* 8k */
  mclk         rate    fs        sr    usb
 {12288000, 8000, 1536, 0xa, 0x0},
 {11289600, 8000, 1408, 0x9, 0x0},
 {18432000, 8000, 2304, 0xc, 0x0},
 {16934400, 8000, 2112, 0xb, 0x0},
 {12000000, 8000, 1500, 0xb, 0x1},
 /* 11.025k */
 /* 16k */
 /* 22.05k */
 /* 32k */
 /* 44.1k */
。。。。。。。。。。。
 /* 48k */
 /* 88.2k */
 /* 96k */
}

static int es8323_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
    struct snd_soc_dai *dai)
    coeff = get_coeff(es8323->sysclk, params_rate(params));
//获得对于的rate和mclk
          if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
 //设置格式,找到对于的codec寄存器数值
    case SNDRV_PCM_FORMAT_S16_LE:
        adciface |= 0x000C;
        daciface |= 0x0018;
    ........................
    /* set iface & srate*/
//设置寄存器DACWL
//ADCWL
    if (coeff >= 0) {
 //主机串行模式,然后采样率,应该是录音
        snd_soc_write(codec, ES8323_ADCCONTROL5, coeff_div[coeff].sr | (coeff_div[coeff].usb) << 4); //采样率的主频
//采样率的主频


6.es8323_set_dai_fmt设置dai的格式
static int es8323_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
//读取接口相关的寄存器
    adciface = snd_soc_read(codec, ES8323_ADC_IFACE);
    daciface = snd_soc_read(codec, ES8323_DAC_IFACE);
   /* set master/slave audio interface */
//看是主还是从模式
// MASTER MODE
        iface |= 0x80;
    // SLAVE MODE
        iface &= 0x7F;
    /* interface format */ADC数据接口的模式
    switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) 
//我们这里是I2S
        adciface &= 0xFC;
        daciface &= 0xF9;
  。。。。。。。
  /* clock inversion */ 时钟翻转
    switch (fmt & SND_SOC_DAIFMT_INV_MASK)
    case SND_SOC_DAIFMT_NB_NF:
  。。。。。。。
    //设置对应的寄存器
ES8323_IFACE, iface);
ES8323_ADC_IFACE, adciface);
ES8323_DAC_IFACE, daciface);


7.static int es8323_mute(struct snd_soc_dai *dai, int mute)
静音函数,静音和播放
//这里soc_pcm_prepare传入0
 //拉低ES8323_CODEC_SET_SPK和ES8323_CODEC_SET_HP控制脚

        es8323_set_gpio(ES8323_CODEC_SET_HP,!es8323->hp_gpio_level);
//静音
    else
        snd_soc_write(codec, ES8323_DACCONTROL3, 0x02); 
//设置音量
 //设置音量
//没有耳机
        es8323_set_gpio(ES8323_CODEC_SET_SPK,es8323->spk_gpio_level);
 //耳机
        es8323_set_gpio(ES8323_CODEC_SET_HP,es8323->hp_gpio_level);


8.rockchip_i2s_trigger
启动传输
static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
switch (cmd)
//开始传输
    case SNDRV_PCM_TRIGGER_RESUME:
    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 //从codec接收
        else
            rockchip_snd_txctrl(i2s, 1);//传输给codec
    case SNDRV_PCM_TRIGGER_SUSPEND:
    case SNDRV_PCM_TRIGGER_STOP:
    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
            if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
//停止
            else
                rockchip_snd_txctrl(i2s, 0); //停止


9.es8323_set_bias_level //设置codec偏压
switch (level)
这里什么都没有做
//进入low power模式,这些寄存器都是这样
        snd_soc_write(codec, ES8323_ANAVOLMANAG, 0x7C);
        snd_soc_write(codec, ES8323_CHIPLOPOW1, 0x00);
        snd_soc_write(codec, ES8323_CHIPLOPOW2, 0x00);
        snd_soc_write(codec, ES8323_CHIPPOWER, 0x00);       
        snd_soc_write(codec, ES8323_ADCPOWER, 0x00);
 //这个和SND_SOC_BIAS_PREPARE一样
 //关闭
        snd_soc_write(codec, ES8323_ADCPOWER, 0xFF);
        snd_soc_write(codec, ES8323_DACPOWER, 0xC0);
        snd_soc_write(codec, ES8323_CHIPLOPOW1, 0xFF);
        snd_soc_write(codec, ES8323_CHIPLOPOW2, 0xFF);
        snd_soc_write(codec, ES8323_CHIPPOWER, 0xFF);
        snd_soc_write(codec, ES8323_ANAVOLMANAG, 0x7B);
    codec->dapm.bias_level = level;