This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TLV320AIC3106:tlv320aic3106

Guru**** 1761415 points
Other Parts Discussed in Thread: TLV320AIC3106, TLV320AIC33, TLV320AIC3007
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/622284/tlv320aic3106-tlv320aic3106

部件号:TLV320AIC3106
主题中讨论的其他部件: TLV320AIC33TLV320AIC3007

你好,团队!

我使用的是tlv320aic3106音频编解码器,我正在正常聆听输出的声音,但在后台也会发出一些噪音。 我可以使用“Left line mixer line 2R bypass” 或“Left line mixer PGAR bypass”来控制噪音,方法是使用alsamixer更改这两个值,但在这种情况下,我的音频会失真或没有声音。如果您可以建议解决方案,这将会非常有帮助。

谢谢!

Pranav

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Pranav,

    我已请我的同事看看这个问题。 您是否具有写入编解码器以复制输出中的噪声的准确寄存器设置?

    此致,

     -Diego Mel é ndez López ñ a
      音频应用工程师

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    先生,我正在附加我正在使用的驱动程序代码。

    /*
     * ALSA SoC TLV320AIC3X编解码器驱动程序
     *
     *作者:     Vladimir Barinov,vbarinov@embeddedalley.com
     *版权所有:  (c) 2007 MontaVista Software,Inc.,<source@mvista.com
     *
     *基于声音/SOC/codecs/wm8753.c,Liam Girdwood著
     *
     *此程序是免费软件;您可以重新分发和/或修改
     *依据GNU通用公共许可证第2版AS的条款
     *由自由软件基金会出版。
     *
     *备注:
     * AIC3X是低功耗立体声音频的驱动程序
     * 编解码器aic31,aic32,aic33,aic3007。
     *
     * 它支持aic33编解码器的全部功能。
     * 与aic32,aic31和aic3007的兼容性如下:
     *   aic32/aic3007   |       aic31
     *-------------------------------  
     *  mono_lout ->不适用 | mono_lout ->不适用
     *                    | IN1L -> LINE1L
     *                    | IN1R -> LINE1R
     *                    | IN2L -> LINE2L
     *                    | IN2R -> LINE2R
     *                    | MIC3L/R ->不适用
     *  中的内部功能被截断
     *  根据文件
     *-------------------------------  
     *
     * 因此,机器层应通过禁用不受支持的输入/输出
     * snd_so_dapm_disable_pin (codec,"mono_lout ")等
     */

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <linux/pm.h>
    #include <linux/i2c.h>
    #include <linux/GPIC.h>
    #include <linux/reguler/consumer.h>
    #include <linux/platform_device.h>
    #include <linux/slab.h>
    #include <sound / core.h>
    #include <sound / pcm.h>
    #include <s声音/pcm_params.h>
    #include <sound / soC.h>
    #include <sound / initval.h>
    #include <sound / tlv.h>
    #include <sound / tlv320aic3x.h>

    包括"tlv320aic3x.h"

    #define AIC3X_NUM_supplies   4.
    静态const char *aic3x_supply_names[AIC3X_NUM_SUPPLYS]={
       "IOVdd",   /* I/O电压*/
       "DVDD",      /*数字内核电压*/
       "AVDD",      /*模拟DAC电压*/
       "DRVDD",   /* ADC模拟和输出驱动器电压*/
    };

    静态list_head (reset_list);

    结构aic3x_priv;

    结构aic3x_disable_NB {
       结构通知程序块NB;
       结构aic3x_priv*aic3x;
    };

    /*编解码器专用数据*/
    结构aic3x_priv{
       struct snd_soc_codec *codec;
       struct reguler_bulate_data supply[AIC3X_NUM_supply];
       结构aic3x_disable_NB disable_NB[AIC3X_NUM_supply];
       枚举snd_so_control_type control_type;
       结构aic3x_setup_data *setup;
       无符号int SYSCLK;
       结构list_head列表;
       INT MASTER;
       int gPIO_reset;
       内置功率;
    #define AIC3X_MODEL _3X 0
    #define AIC3X_MODEL _33 1.
    #define AIC3X_MODEL _3007 2.
       U16型号;
    };

    /*
     * AIC3X寄存器高速缓存
     *我们无法读取AIC3X寄存器空间
     *使用2线进行设备控制,因此我们会缓存它们。
     *缓存重置寄存器没有意义
     */
    静态连接u8 aic3x_reg[AIC3X_CACHEREGNUM]={
       0x00,0x00,0x00,0x10,   /* 0 */
       0x04,0x00,0x00,0x00,   /* 4 */
       0x00,0x00,0x00,0x01,   /* 8 */
       0x00,0x00,0x00,0x80,   /* 12 */
       0x80,0xff,0xff,0x78,   /* 16 */
       0x78,0x78,0x78,0x78,   /* 20 */
       0x78,0x00,0x00,0xFE,   /* 24 */
       0x00,0x00,0xFE,0x00,   /* 28 */
       0x18,0x18,0x00,0x00,   /* 32 */
       0x00,0x00,0x00,0x00,   /* 36 */
       0x00,0x00,0x00,0x80,   /* 40 */
       0x80,0x00,0x00,0x00,   /* 44 */
       0x00,0x00,0x00,0x04,   /* 48 */
       0x00,0x00,0x00,0x00,   /* 52 */
       0x00,0x00,0x04,0x00,   /* 56 */
       0x00,0x00,0x00,0x00,   /* 60 */
       0x00,0x04,0x00,0x00,   /* 64 */
       0x00,0x00,0x00,0x00,   /* 68 */
       0x04,0x00,0x00,0x00,   /* 72 */
       0x00,0x00,0x00,0x00,   /* 76 */
       0x00,0x00,0x00,0x00,   /* 80 */
       0x00,0x00,0x00,0x00,   /* 84 */
       0x00,0x00,0x00,0x00,   /* 88 */
       0x00,0x00,0x00,0x00,   /* 92 */
       0x00,0x00,0x00,0x00,   /* 96 */
       0x00,0x00,0x02,   /* 100 */
    };

    /*
     *从aic3x寄存器空间读取。 仅用于此功能的是IF
     *希望从同时具有只读功能的寄存器中读取易失位
     *和读/写位。 所有其他情况都应使用snd_so_read。
     */
    静态int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
               U8 *值)

       u8 *cache = codec->reg_cache;

       如果(codec->cache_only)
          返回-EINVAL;
       IF (REG >= AIC3X_CACHEREGNUM)
          返回-1;

       codec->cache_bypass =1;
       *value = snd_so_read(codec, reg);
    printk ("register=  %d  value="%d \n",reg,* value);
       codec->cache_bypass =0;

       cache[reg]=*值;

       返回0;
    }

    #define SOC_DAPM_SINGLE_AIC3X (xname,reg,shift,mask,invert)\
    {   .iface = SNDRV_CTL_Elem_iface_mixer,.name = xname,\
       信息= snd_soc_info_volsw,\
       get = snd_so_dapm_Get_volsw,.put = snd_so_dapm_put volsw_aic3x,\
       .private_value = so_singer_value(reg, shift, mask, inver)}

    /*
     *当!0xF与0xF位字段断开连接时,所有输入线路均已连接,
     *因此我们必须使用特定的dapm_put调用输入混音器
     */
    静态int snd_so_dapm_put volsw_aic3x (struct snd_kcontrol *kcontrol,
                   struct snd_ctl_elem_value *uccontrol)

       struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
       struct snd_soc_dapm_widget *widget = wlist->widget[0];
       struct soc_mixer_control *mc =
          (struct soc_mixer_control *)kcontrol->private_value;
       unsigned int reg = mc -> reg;
       unsigned int shift = mc -> shift;
       Int max = mc -> max;
       unsigned int mask =(1 << FLS (max)))- 1;
       unsigned int invert = mc -> inver;
       unsigned short val, val_mask;
       Int ret (内部);
       结构snd_so_dapm_path *path;
       找到Int = 0;

       Val =(uccontrol->value.integer.value[0]& mask);

       掩码= 0xF;
       如果(val)
          Val =掩码;

       IF (反转)
          Val =掩码- Val;
       Val_mask =掩码<<移位;
       Val = val <<移位;

       mutex_lock(&wide->codec->mutex);

       如果(snd_soc_test_bits (小部件->编解码器,reg,val_mask,val)){
          /*使用kcontrol */查找dapm小部件路径assoc
          list_for _each_entry (路径,&widget->dapm->card->路径,列表){
             if (path->kcontrol != kcontrol)(如果路径->kcontrol != kcontrol)
                继续;

             /*找到,现在检查类型*/
             找到= 1;
             如果(val)
                /*新连接*/
                path->connect =反转? 0:1;
             否则
                /*旧连接必须关闭*/
                path->connect =反转? 1:0;

             dapm_mark_dirty (path->source,"tlv320aic3x source");
             dapm_mark_dirty (path->sink,"tlv320aic3x sink");

             中断;
          }

          如果(找到)
             snd_soc_dapm_sync(widget->dapm);
       }

       RET = snd_so_update_bits (小部件->编解码器,reg,val_mask,val);

       mutex_unlock(&wide->codec->mutex);
       返回台;
    }

    静态const char *aic3x_left_DAC_mix[]={"DAC_L1","DAC_L3","DAC_L2"};
    静态const char *aic3x_right_doc_mix[]={"DAC_R1","DAC_R3","DAC_R2"};
    静态const char *aic3x_left_hpcom_mux[]=
       {“HPLOUT差分”,“常数VCM”,“单端”};
    静态const char *aic3x_right_hpcom_mux[]=
       {"HPROUT","恒定VCM","单端",
         "HPLCOM的差分","外部反馈";
    静态const char *aic3x_linein_mode_mix[]={“单端”,“差异”};
    静态const char *aic3x_adc_hpf[]=
       {"Disabled","0.0045xFs","0.0125xFs","0.025xFs"};

    #define LDAC_ENUM   0
    #define RDAC_ENUM   1.
    #define LHPCOM_ENUM   2.
    #define RHPCOM_ENUM   3.
    #define LINE1L_2_L_ENUM   4.
    #define LINE1L_2_R_ENUM   5.
    #define LINE1R_2_L_ENUM   6.
    #define LINE1R_2_R_ENUM   7.
    #define LINE2L_ENUM   8.
    #define LINE2R_ENUM   9.
    #define ADC_HPF_ENUM   10.

    静态结构soc_enum aic3x_enum []={
       soc_enum单一(dac线路MUX,6,3,aic3x_left_dac _mux),
       soc_enum单一(dac线路MUX,4,3,aic3x_right_dac _mux),
       soc_enum单个(HPLCOM_CFG,4,3,aic3x_left_hpcom_mux),
       soc_enum单个(HPRCOM_CFG,3,5,aic3x_right_hpcom_mux),
       so_enum单一(LINE1L_2_LADC_CTRL,7,2,aic3x_linein_mode_mux),
       so_enum单一(LINE1L_2_RADC_CTRL,7,2,aic3x_linein_mode_mux),
       so_enum单一(LINE1R_2_LADC_CTRL,7,2,aic3x_linein_mode_mux),
       so_enum单一(LINE1R_2_RADC_CTRL,7,2,aic3x_linein_mode_mux),
       so_enum单一(LINE2L_2_LADC_CTRL,7,2,aic3x_linein_mode_mux),
       so_enum单一(LINE2R_2_RADC_CTRL,7,2,aic3x_linein_mode_mux),
       SOC_ENUM_DOUBLE (AIC3X_CODER_DFILT_CTRL,6,4,4,aic3x_ADC_hpf),
    };

    /*
     * DAC数字卷。 从- 63.5 到0 dB,以0.5 dB为步长
     */
    静态声明_TLV_DB_scale (DAC_tlv,-6350,50,0);
    /* ADC PGA增益量。 从0到59.5 dB,以0.5 dB为步长*/
    静态声明_TLV_DB_scale (ADC_tlv,0,50,0);
    /*
     *输出阶段容积。 从- 78.3 到0 dB。 静音低于- 78.3 dB。
     *步长在大部分刻度上约为0.5 dB,但在增加
     *接近极低水平。
     *定义dB刻度,以便在-55到0 dB的范围内,它通常是正确的
     *但在该值以下(以及不计算的位置),dB差异会增加
     *如此多)。 此设置为寄存器显示-50 dB (实际值为- 50.3 dB)
     *寄存器值117的值为100和- 58.5 dB (实际值为- 78.3 dB)。
     */
    静态声明_TLV_DB_scale (output_stage_tlv,-5900,50,1);

    静态const结构snd_kcontrol_new aic3x_snd_control[]={
       /*输出*/
       SOC_DOULE_R_TLV ("PCM播放音量",
             LDAC_VOL,RDAC_VOL,0,0x7f,1, dac _tlv),

       /*
       *映射到输出混音器开关的输出控件。 请注意这些是
       *仅适用于交换的L到R和R到L路由。 请参阅下面的立体声控件
       *用于L到L和R到R直路由。
       */
       SOC_SINGLE_TLV ("左混音器Line2R旁通音量",
                LINE2R_2_LLOPM_VOL,0118,1,OUTPT_STEG_tlv),
       SOC_SINGLE_TLV ("左混音器PGAR旁路音量",
                PGAR_2_LLOPM_VOL,0118,1,OUTPT_STAGE _tlv),
       SOC_SINGLE_TLV ("左混音器DACR1回放音量",
                DACR1_2_LLOPM_VOL,0118,1,output_stage_tlv),

       SOC_SINGLE_TLV ("右混音器Line2L旁通音量",
                LINE2L_2_RLOPM_VOL,0118,1,output_stage_tlv),
       SOC_SINGLE_TLV ("右混音器PGAL旁路音量",
                PGAL_2_RLOPM_VOL,0118,1,output_stage_tlv),
       SOC_SINGLE_TLV ("右混音器DACL1播放音量",
                DACL1_2_RLOPM_VOL,0118,1,output_stage_tlv),

       SOC_SINGLE_TLV ("左HP Mixer Line2R Bypass Volume ",
                LINE2R_2_HPLOUT_VOL,0118,1,OUTPT_STAGE _tlv),
       SOC_SINGLE_TLV ("左HP Mixer PGAR Bypass Volume",
                PGAR_2_HPLOUT_VOL,0118,1,OUTPT_STAGE _tlv),
       SOC_SINGLE_TLV (“左HP Mixer DACR1 Playback Volume”,
                DACR1_2_HPLOUT_VOL,0118,1,OUTPT_STAGE _tlv),

       SOC_SINGLE_TLV ("右侧HP Mixer Line2L Bypass Volume",
                LINE2L_2_HPROUT_VOL,0118,1,OUTPUT_STAGE _tlv),
       SOC_SINGLE_TLV ("右侧HP Mixer PGAL旁路音量",
                PGAL_2_HPROUT_VOL,0118,1,output_stage_tlv),
       SOC_SINGLE_TLV ("右侧HP混音器DACL1播放音量",
                DACL1_2_HPROUT_VOL,0118,1,OUTPUT_STAGE _tlv),

       SOC_SINGLE_TLV ("左HPCOM混音器Line2R旁通音量",
                LINE2R_2_HPLCOM_VOL,0118,1,OUTPT_STAGE _tlv),
       SOC_SINGLE_TLV ("Left HPCOM Mixer PGAR Bypass Volume",
                PGAR_2_HPLCOM_VOL,0118,1,OUTPT_STAGE _tlv),
       SOC_SINGLE_TLV ("左HPCOM混音器DACR1播放音量",
                DACR1_2_HPLCOM_VOL,0118,1,OUTPT_STAGE _tlv),

       SOC_SINGLE_TLV ("右HPCOM混音器Line2L旁通音量",
                LINE2L_2_HPRCOM_VOL,0118,1,output_stage_tlv),
       SOC_SINGLE_TLV ("右HPCOM混音器PGAL旁路音量",
                PGAL_2_HPRCOM_VOL,0118,1,output_stage_tlv),
       SOC_SINGLE_TLV ("右HPCOM混音器DACL1播放音量",
                DACL1_2_HPRCOM_VOL,0118,1,OUTPT_STAGE _tlv),

       /*立体声输出控制,用于直接L到L和R到R路由*/
       SOC_DOULE_R_TLV ("Line Line2 Bypass Volume",
             LINE2L_2_LLOPM_VOL,LINE2R_2_RLOPM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("Line PGA Bypass Volume",
             PGAL_2_LLOPM_VOL,PGAR_2_RLOPM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("Line DAC Playback Volume",
             DACL1_2_LLOPM_VOL,DACR1_2_RLOPM_VOL,
             0118,1,output_stage_tlv),

       SOC_DOULE_R_TLV ("单声道2旁路音量",
             LINE2L_2_MONOLOPM_VOL,LINE2R_2_MONOLOPM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("单声道PGA旁通量",
             PGAL_2_MONOLOPM_VOL,PGAR_2_MONOLOPM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("单声道DAC播放音量",
             DACL1_2_MONOLOPM_VOL,DACR1_2_MONOLOPM_VOL,
             0118,1,output_stage_tlv),

       SOC_DOULE_R_TLV ("HP Line2旁路音量",
             LINE2L_2_HPLOUT_VOL,LINE2R_2_HPROUT_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("HP PGA旁路音量",
             PGAL_2_HPLOUT_VOL,PGAR_2_HPROUT_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("HP DAC播放音量",
             DACL1_2_HPLOUT_VOL,DACR1_2_HPROUT_VOL,
             0118,1,output_stage_tlv),

       SOC_DOULE_R_TLV ("HPCOM Line2 Bypass Volume",
             LINE2L_2_HPLCOM_VOL,LINE2R_2_HPRCOM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("HPCOM PGA旁路容积",
             PGAL_2_HPLCOM_VOL,PGAR_2_HPRCOM_VOL,
             0118,1,output_stage_tlv),
       SOC_DOULE_R_TLV ("HPCOM DAC播放音量",
             DACL1_2_HPLCOM_VOL,DACR1_2_HPRCOM_VOL,
             0118,1,output_stage_tlv),

       /*输出针脚静音控制*/
       SOC_DOULE_R ("线路播放开关",LLOPM_CTRL,RLOPM_CTRL,3,
              0x01,0),
       SOC_single ("单声道播放开关",MONOLOPM_CTRL,3,0x01,0),
       SOC_DOULE_R ("HP回放开关",HPLOUT_CTRL,HPROUT_CTRL,3,
              0x01,0),
       SOC_DOULE_R ("HPCOM播放开关",HPLCOM_CTRL,HPRCOM_CTRL,3,
              0x01,0),

       /*
       *注意:请小心启用自动输入增益控制器。 它可以
       *当ADC打开且永远不会返回时,将PGA调整为最大值。
       */
       SOC_DOULE_R ("AGC Switch",LAGC_CTRL_A,Ragc_CTRL_A,7,0x01, 0),

       /*输入*/
       SOC_DOULE_R_TLV ("PGA捕获音量",LADC_VOL,RADC_VOL,
             0119,0,adc_tlv),
       SOC_DOULE_R ("PGA捕获开关",LADC_VOL,RADC_VOL,7,0x01, 1),

       soc_enum ("ADC HPF切断",aic3x_enum[ADC_HPF_ENUM]),
    };

    /*
     * D类放大器增益。 从0到18 dB,以6 dB为增量
     */
    静态声明_TLV_DB_scale (classd_amp_tlv,0600,0);

    静态const结构snd_kcontrol_new aic3x_classd_amp_gain _ctrl =
       SOC_DOULE_TLV ("D类放大器增益",CLASSD_CTRL,6,4,3, 0,classd_amp_tlv);

    /*左DAC Mux */
    静态结构snd_kcontrol_new aic3x_left_dac _mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LDAC_ENUM]);

    /*右DAC Mux */
    静态结构snd_kcontrol_new aic3x_right_dac _mix_controls =
    so_dapm_enum ("Route",aic3x_enum[dac enum]);

    /*左HPCOM Mux */
    静态结构snd_kcontrol_new aic3x_left_hpcom_mux_controls =
    so_dapm_enum ("Route",aic3x_enum[LHPCOM_ENUM]);

    /*右HPCOM Mux */
    静态结构snd_kcontrol_new aic3x_right_hpcom_mux_controls =
    so_dapm_enum ("Route",aic3x_enum[RHPCOM_ENUM]);

    /*左混音器*/
    静态const结构snd_kcontrol_new aic3x_left_line_mixer_controls[]={
       SOC_DAMP_single ("Line2L旁路开关",LINE2L_2_LLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAL旁路开关",PGAL_2_LLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACL1开关",DACL1_2_LLOPM_VOL,7,1,0),
       SOC_DAMP_single ("Line2R旁路开关",LINE2R_2_LLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAR旁路开关",PGAR_2_LLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACR1 Switch",DACR1_2_LLOPM_VOL,7,1,0),
    };

    /*右混音器*/
    静态const结构snd_kcontrol_new aic3x_right_line_mixer_control[]={
       SOC_DAMP_single ("Line2L旁路开关",LINE2L_2_RLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAL旁路开关",PGAL_2_RLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACL1开关",DACL1_2_RLOPM_VOL,7,1,0),
       SOC_DAMP_single ("Line2R旁路开关",LINE2R_2_RLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAR旁路开关",PGAR_2_RLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACR1 Switch",DACR1_2_RLOPM_VOL,7,1,0),
    };

    /*单声道混音器*/
    静态const结构snd_kcontrol_new aic3x_mono_mixer_control[]={
       SOC_DAMP_single ("Line2L旁路开关",LINE2L_2_MONOLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAL旁路开关",PGAL_2_MONOLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACL1开关",DACL1_2_MONOLOPM_VOL,7,1,0),
       SOC_DAMP_single ("Line2R旁路开关",LINE2R_2_MONOLOPM_VOL,7,1,0),
       SOC_DAMP_single ("PGAR旁路开关",PGAR_2_MONOLOPM_VOL,7,1,0),
       SOC_DAMP_single ("DACR1 Switch",DACR1_2_MONOLOPM_VOL,7,1,0),
    };

    /*左HP混音器*/
    静态const结构snd_kcontrol_new aic3x_left_hp_mixer_control[]={
       SOC_DAPM_single ("Line2L旁路开关",LINE2L_2_HPLOUT_VOL,7,1,0),
       SOC_DAPM_single ("PGAL旁路开关",PGAL_2_HPLOUT_VOL,7,1,0),
       SOC_DAPM_single ("DACL1开关",DACL1_2_HPLOUT_VOL,7,1,0),
       SOC_DAPM_single ("Line2R旁路开关",LINE2R_2_HPLOUT_VOL,7,1,0),
       SOC_DAPM_single ("PGAR旁路开关",PGAR_2_HPLOUT_VOL,7,1,0),
       SOC_DAPM_single ("DACR1 Switch",DACR1_2_HPLOUT_VOL,7,1,0),
    };

    /*右HP混音器*/
    静态结构snd_kcontrol_new aic3x_right_hp_mixer_control[]={
       SOC_DAPM_single ("Line2L旁路开关",LINE2L_2_HPROUT_VOL,7,1,0),
       SOC_DAPM_single ("PGAL旁路开关",PGAL_2_HPROUT_VOL,7,1,0),
       SOC_DAPM_single ("DACL1开关",DACL1_2_HPROUT_VOL,7,1,0),
       SOC_DAPM_single ("Line2R旁路开关",LINE2R_2_HPROUT_VOL,7,1,0),
       SOC_DAPM_single ("PGAR旁路开关",PGAR_2_HPROUT_VOL,7,1,0),
       SOC_DAPM_single ("DACR1 Switch",DACR1_2_HPROUT_VOL,7,1,0),
    };

    /*左HPCOM混音器*/
    静态const结构snd_kcontrol_new aic3x_left_hpcom_mixer_control[]={
       SOC_DAPM_single ("Line2L旁路开关",LINE2L_2_HPLCOM_VOL,7,1,0),
       SOC_DAPM_single ("PGAL旁路开关",PGAL_2_HPLCOM_VOL,7,1,0),
       SOC_DAPM_single ("DACL1开关",DACL1_2_HPLCOM_VOL,7,1,0),
       SOC_DAPM_single ("Line2R旁路开关",LINE2R_2_HPLCOM_VOL,7,1,0),
       SOC_DAPM_single ("PGAR旁路开关",PGAR_2_HPLCOM_VOL,7,1,0),
       SOC_DAPM_single ("DACR1 Switch",DACR1_2_HPLCOM_VOL,7,1,0),
    };

    /*右HPCOM混音器*/
    静态const结构snd_kcontrol_new aic3x_right_hpcom_mixer_control[]={
       SOC_DAMP_single ("Line2L旁路开关",LINE2L_2_HPRCOM_VOL,7,1,0),
       SOC_DAMP_single ("PGAL旁路开关",PGAL_2_HPRCOM_VOL,7,1,0),
       SOC_DAMP_single ("DACL1开关",DACL1_2_HPRCOM_VOL,7,1,0),
       SOC_DAMP_single ("Line2R旁路开关",LINE2R_2_HPRCOM_VOL,7,1,0),
       SOC_DAMP_single ("PGAR旁路开关",PGAR_2_HPRCOM_VOL,7,1,0),
       SOC_DAMP_single ("DACR1 Switch",DACR1_2_HPRCOM_VOL,7,1,0),
    };

    /*左PGA混音器*/
    静态结构snd_kcontrol_new aic3x_left_PGA_Mixer_control[]={
       SOC_DAMP_SINGLE_AIC3X ("Line1L Switch",LINE1L_2_LADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Line1R Switch",LINE1R_2_LADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Line2L Switch",LINE2L_2_LADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Mic3L Switch",MIC3LR_2_LADC_CTRL,4,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Mic3R Switch",MIC3LR_2_LADC_CTRL,0,1,1),
    };

    /*右PGA混音器*/
    静态结构snd_kcontrol_new aic3x_right_pga混合器控件[]={
       SOC_DAMP_SINGLE_AIC3X ("Line1R Switch",LINE1R_2_RADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Line1L Switch",LINE1L_2_RADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Line2R Switch",LINE2R_2_RADC_CTRL,3,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Mic3L Switch",MIC3LR_2_RADC_CTRL,4,1,1),
       SOC_DAMP_SINGLE_AIC3X ("Mic3R Switch",MIC3LR_2_RADC_CTRL,0,1,1),
    };

    /*左线1 Mux */
    静态结构snd_kcontrol_new aic3x_left_line1l_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE1L_2_L_ENUM]);
    静态结构snd_kcontrol_new aic3x_right_line1l_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE1L_2_R_ENUM]);

    /*右线1 Mux */
    静态结构snd_kcontrol_new aic3x_right_line1r_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE1R_2_R_ENUM]);
    静态结构snd_kcontrol_new aic3x_left_line1r_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE1R_2_L_ENUM]);

    /*左线2 Mux */
    静态结构snd_kcontrol_new aic3x_left_line2_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE2L_ENUM]);

    /*右线2 Mux */
    静态结构snd_kcontrol_new aic3x_right_lin22_mix_controls =
    so_dapm_enum ("Route",aic3x_enum[LINE2R_ENUM]);

    静态结构snd_so_dapm_widget aic3x_dapm_widget[]={
       /*左DAC至左输出*/
       Snd_SOC_DAPM_DAC ("左DAC ","左回放",DAC_PWR,7,0),
       Snd_SOC_DAPM_MUX ("左DAC Mux",Snd_SOC_NOPM,0,0,
             &aic3x_left_DAC_mix_controls),
       Snd_SOC_DAPM_MUX ("Left HPCOM Mux",Snd_SOC_NOPM,0,0,
             &aic3x_left_hpcom_mux_controls),
       Snd_SOC_DAPM_PGA ("左线路输出",LLOPM_CTRL,0,0,NULL, 0),
       Snd_SOC_DAPM_PGA ("左侧HP输出",HPLOUT_CTRL,0,0,NULL, 0),
       Snd_SOC_DAPM_PGA ("左侧HP COM",HPLCOM_CTRL,0,0,NULL, 0),

       /*右DAC至右输出*/
       Snd_SOC_DAPM_DAC ("右DAC ","右回放",DAC_PWR,6,0),
       Snd_SOC_DAPM_MUX ("右DAC Mux",Snd_SOC_NOPM,0,0,
             &aic3x_right_dac _mix_controls),
       Snd_SOC_DAPM_MUX ("右侧HPCOM Mux",Snd_SOC_NOPM,0,0,
             &aic3x_right_hpcom_mux_controls),
       Snd_SOC_DAPM_PGA ("右线路输出",RLOPM_CTRL,0,0,NULL, 0),
       Snd_SOC_DAPM_PGA ("右侧HP输出",HPROUT_CTRL,0,0,NULL, 0),
       Snd_SOC_DAPM_PGA ("右侧HP COM",HPRCOM_CTRL,0,0,NULL, 0),

       /*单色输出*/
       Snd_SOC_DAPM_PGA ("单声道输出",MONOLOPM_CTRL,0,0,NULL, 0),

       /*输入至左ADC */
       Snd_SOC_DAPM_ADC ("左ADC ","左捕获",LINE1L_2_LADC_CTRL,2,0),
       snd_so_dapm_mixer ("Left PGA Mixer",snd_so_npm,0,0,
               &aic3x_left_PGA_Mixer_controls[0],
               array_size (aic3x_left_PGA_mixer_controls)),
       Snd_SOC_DAPM_MUX ("Left Line1L Mux",Snd_SOC_NOPM,0,0,
             &aic3x_left_line1l_mix_controls),
       Snd_SOC_DAPM_MUX ("Left Line1R Mux",Snd_SOC_NOPM,0,0,
             &aic3x_left_line1r_mix_controls),
       Snd_SOC_DAPM_MUX ("Left Line2L Mux",Snd_SOC_NOPM,0,0,
             &aic3x_left_line2_mix_controls),

       /*输入至右侧ADC */
       Snd_SOC_DAPM_ADC ("右侧ADC","右侧捕获",
             LINE1R_2_RADC_CTRL,2,0),
       Snd_SOC_DAPM_Mixer ("右PGA Mixer ",Snd_SOC_NOPM,0,0,
               &aic3x_right_PGA_Mixer_controls[0],
               array_size (aic3x_right_PGA_mixer_controls)),
       Snd_SOC_DAPM_MUX ("右行1L Mux",Snd_SOC_NOPM,0,0,
             &aic3x_right_line1l_mix_controls),
       Snd_SOC_DAPM_MUX ("Right Line1R Mux",Snd_SOC_NOPM,0,0,
             &aic3x_right_line1r_mix_controls),
       Snd_SOC_DAPM_MUX ("Right Line2R Mux",Snd_SOC_NOPM,0,0,
             &aic3x_right_lin22_mix_controls),

       /*
       *不是真正的麦克风偏置小部件,但功能相似。 这是动态的
       *控制GPIO1数字麦克风调制器时钟输出功能
       *使用数字麦克风。
       */
       Snd_SOC_DAPM_REG (Snd_SOC_dapm_micbias,"GPIO1 dmic modclk",
             AIC3X_GPIO1_REG,4,0xF,
             AIC3X_GPIO1_FUNC_DIGITAL MIC_MODCLK,
             AIC3X_GPIO1_FUNC_DISABLED),

       /*
       *也有类似的功能,如麦克风偏置。 使用选择数字麦克风
       *可配置的过采样率,而不是ADC转换器。
       */
       Snd_SOC_DAPM_REG (Snd_SOC_Dapm_micbias,"DMic rate 128",
             AIC3X_ASD_INTF_CtrlA,0,3,1,0),
       Snd_SOC_DAPM_REG (Snd_SOC_Dapm_micbias,"DMic Rate 64",
             AIC3X_ASD_INTF_CtrlA,0,3,2,0),
       Snd_SOC_DAPM_REG (Snd_SOC_Dapm_micbias,"DMic rate 32",
             AIC3X_ASD_INTF_CtrlA,0,3,3,0),

       /*麦克风偏置*/
       Snd_SOC_DAPM_REG (Snd_SOC_dapm_micbias,"Mic Bias 2V",
             MICBIAS_CTRL,6,3,1,0),
       Snd_SOC_DAPM_REG (Snd_SOC_dapm_micbias,"Mic Bias 2.5V),
             MICBIAS_CTRL,6,3,2,0),
       Snd_SOC_DAPM_REG (Snd_SOC_Dapm_micbias,"Mic Bias AVDD",
             MICBIAS_CTRL,6,3,3,0),

       /*输出混音器*/
       Snd_SOC_DAPM_Mixer ("左线路混音器",Snd_SOC_NOPM,0,0,
               &aic3x_left_line_mixer_controls[0],
               array_size (aic3x_left_line_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("右线路混音器",Snd_SOC_NOPM,0,0,
               &aic3x_right_line_mixer_controls[0],
               array_size (aic3x_right_line_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("单声道混音器",Snd_SOC_NOPM,0,0,
               &aic3x_mono_mixer_control[0],
               array_size (aic3x_mono_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("左侧HP Mixer ",Snd_SOC_NOPM,0,0,
               &aic3x_left_hp_mixer_control[0],
               array_size (aic3x_left_hp_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("右侧HP Mixer ",Snd_SOC_NOPM,0,0,
               &aic3x_right_hp_mixer_control[0],
               array_size (aic3x_right_hp_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("Left HPCOM Mixer",Snd_SOC_NOPM,0,0,
               &aic3x_left_hpcom_mixer_control[0],
               array_size (aic3x_left_hpcom_mixer_controls)),
       Snd_SOC_DAPM_Mixer ("右HPCOM Mixer ",Snd_SOC_NOPM,0,0,
               &aic3x_right_hpcom_mixer_control[0],
               array_size (aic3x_right_hpcom_mixer_controls)),

       Snd_SOC_DAPM_OUTP("LLOut"),
       Snd_SOC_DAPM_OUTP("RLOUT"),
       Snd_SOC_DAPM_OUTPUT ("单声道输出"),
       Snd_SOC_DAPM_OUTPUT ("HPLOUT"),
       Snd_SOC_DAPM_OUTPUT ("HPROUT"),
       Snd_SOC_DAPM_OUTP("HPLCOM"),
       Snd_SOC_DAPM_OUTP("HPRCOM"),

       Snd_SOC_DAPM_INPUT ("MIC3L"),
       Snd_SOC_DAPM_INPUT ("MIC3R"),
       Snd_SOC_DAPM_INPUT ("LINE1L"),
       Snd_SOC_DAPM_INPUT ("LINE1R"),
       Snd_SOC_DAPM_INPUT ("LINE2L"),
       Snd_SOC_DAPM_INPUT ("LINE2R"),

       /*
       *编解码器内检测块的虚拟输出引脚。 这可能是
       *用于在需要GPIO或检测功能时保持编解码器偏置打开。
       *使用输入插孔和麦克风偏置强制引脚打开或构建路径
       *小工具。
       */
       Snd_SOC_DAPM_OUTPUT ("检测"),
    };

    静态结构snd_so_dapm_widget aic3007_dapm_widget[]={
       /* D类输出*/
       Snd_SOC_DAPM_PGA ("左侧D类输出",CLASSD_CTRL,3,0,NULL, 0),
       Snd_SOC_DAPM_PGA ("右D类输出",CLASSD_CTRL,2,0,NULL, 0),

       Snd_SOC_DAPM_OUTPUT ("SPOP"),
       Snd_SOC_DAPM_OUTPUT ("SPOM"),
    };

    静态连接结构snd_so_dapm_route intercon[]={
       /*左侧输入*/
       {"Left Line1L Mux","single-ended ","LINE1L"},
       {"Left Line1L Mux","Different","LINE1L"},

       {"Left Line2L Mux","single-ended ","LINE2L"},
       {"Left Line2L Mux","Different","LINE2L"},

       {"Left PGA Mixer","Line1L Switch","Left Line1L Mux"},
       {"Left PGA Mixer","Line1R Switch","Left Line1R Mux"},
       {"Left PGA Mixer","Line2L Switch","Left Line2L Mux"},
       {"Left PGA Mixer (左PGA混合器)","Mic3L Switch (Mic3L开关)","MIC3L"},
       {"Left PGA Mixer (左PGA混合器)","Mic3R Switch","MIC3R"},

       {"Left ADC",NULL,"Left PGA Mixer"},
       {"Left ADC",NULL,"GPIO1 dmic modclk"},

       /*右输入*/
       {"Right Line1R Mux","单端","LINE1R"},
       {"Right Line1R Mux","Different","LINE1R"},

       {"Right Line2R Mux","单端","LINE2R"},
       {"Right Line2R Mux","Different","LINE2R"},

       {"Right PGA Mixer","Line1L Switch","Rright Line1L Mux"},
       {"Right PGA Mixer","Line1R Switch","Rright Line1R Mux"},
       {"Right PGA Mixer","Line2R Switch","Rright Line2R Mux"},
       {"Right PGA Mixer","Mic3L Switch","MIC3L"},
       {"Right PGA Mixer (右PGA混合器)","Mic3R Switch","MIC3R"},

       {"Right ADC",NULL,"RIGHT PGA Mixer"},
       {"Right ADC",NULL,"GPIO1 dmic modclk"},

       /*
       *数字麦克风启用和GPIO1调制器时钟之间的逻辑路径
       *输出功能
       */
       {"GPIO1 dmic modclk",NULL,"DMic rate 128"},
       {"GPIO1 dmic modclk",NULL,"DMic rate 64"},
       {"GPIO1 dmic modclk",NULL,"DMic rate 32"},

       /*左DAC输出*/
       {"Left DAC Mux","DAC_L1","Left DAC"},
       {"Left DAC Mux","DAC_L2","L向 左DAC"},
       {"Left DAC Mux","DAC_L3","Left DAC"},

       /*右DAC输出*/
       {"Right DAC Mux","DAC_R1","RIGHT DAC"},
       {"RIGHT DAC MUX","DAC_R2","RIGHT DAC"},
       {"Right DAC Mux","DAC_R3","Rright DAC"},

       /*左行输出*/
       {"Left Line Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Left Line Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Left Line Mixer","DACL1 Switch","Left DAC Mux"},
       {"Left Line Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"左混音器","PGAR旁路开关","右PGA混音器"},
       {"Left Line Mixer","DACR1 Switch","Right DAC Mux"},

       {"左线输出",NULL,"左线混合器"},
       {"Left Line Out (左线路输出)",NULL,"Left DAC Mux (左DAC多路复用器)"},
       {"LLOut",NULL,"Left Line Out"},

       /*右行输出*/
       {"Right Line Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Right Line Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Right Line Mixer","DACL1 Switch","Left DAC Mux"},
       {"Right Line Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"右混音器","PGAR旁路开关","右PGA混音器"},
       {"Right Line Mixer","DACR1 Switch","RIGHT DAC Mux"},

       {"右线路输出",NULL,"右线路混合器"},
       {"右线路输出",NULL,"右DAC Mux"},
       {"RLOUT",NULL,"右线路输出"},

       /*单色输出*/
       {"Mono Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Mono Mixer","PGAL旁路开关","左PGA Mixer"},
       {"Mono Mixer","DACL1 Switch","Left DAC Mux"},
       {"Mono Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"单声道混音器","PGAR旁路开关","右PGA混音器"},
       {"Mono Mixer","DACR1 Switch","Right DAC Mux"},

       {"Mono Out (黑白输出)",NULL,"Mono Mixer (黑白混音器)"},
       {"mono_lout},NULL,"单声道输出"},

       /*左HP输出*/
       {"Left HP Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Left HP Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Left HP Mixer","DACL1 Switch","Left DAC Mux"},
       {"Left HP Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"Left HP Mixer","PGAR Bypass Switch","Rright PGA Mixer"},
       {"Left HP Mixer","DACR1 Switch","Right DAC Mux"},

       {"Left HP Out (左HP输出)",NULL,"Left HP Mixer (左HP混音器)"},
       {"Left HP Out (左侧HP输出)",NULL,"Left DAC Mux (左DAC多路复用器)"},
       {"HPLOUT",NULL,"左HP OUT "},

       /*右侧HP输出*/
       {"Right HP Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Right HP Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Right HP Mixer","DACL1 Switch","Left DAC Mux"},
       {"Right HP Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"Right HP Mixer","PGAR Bypass Switch","Rright PGA Mixer"},
       {"Right HP Mixer","DACR1 Switch","Rright DAC Mux"},

       {"右侧HP输出",NULL,"右侧HP混音器"},
       {"Right HP Out (右侧HP输出)",NULL,"Rright DAC Mux"},
       {"HPROUT",NULL,"右侧HP输出"},

       /*左HPCOM输出*/
       {"Left HPCOM Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Left HPCOM Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Left HPCOM Mixer","DACL1 Switch","Left DAC Mux"},
       {"Left HPCOM Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"Left HPCOM Mixer (左HPCOM混音器)","PGAR Bypass Switch"(PGAR旁路开关),"Rright PGA Mixer (右PGA混音器)"},
       {"Left HPCOM Mixer","DACR1 Switch","Rright DAC Mux"},

       {"Left HPCOM Mux","Differential of HPLOUT","Left HP Mixer"},
       {"Left HPCOM Mux","Constant VCM","Left HPCOM Mixer"},
       {"Left HPCOM Mux","single-ended,"Left HPCOM Mixer"},
       {"Left HP COM",NULL,"Left HPCOM Mux"},
       {"HPLCOM",NULL,"Left HP COM"},

       /*右HPCOM输出*/
       {"Right HPCOM Mixer","Line2L Bypass Switch","Left Line2L Mux"},
       {"Right HPCOM Mixer","PGAL Bypass Switch","Left PGA Mixer"},
       {"Right HPCOM Mixer","DACL1 Switch","Left DAC Mux"},
       {"Right HPCOM Mixer","Line2R Bypass Switch","Rright Line2R Mux"},
       {"Right HPCOM Mixer","PGAR Bypass Switch","Rright PGA Mixer"},
       {"Right HPCOM Mixer","DACR1 Switch","Rright DAC Mux"},

       {"Right HPCOM Mux","Differential of HPROUT","Rright HP Mixer"},
       {"Right HPCOM Mux","Constant VCM","Rright HPCOM Mixer"},
       {"Right HPCOM Mux","single-ended,"Rright HPCOM Mixer"},
       {"Right HPCOM Mux","Differential of HPLCOM","Left HPCOM Mixer"},
       {"Right HPCOM Mux","external feedback","Rright HPCOM Mixer"},
       {"Right HP COM",NULL,"Rright HPCOM Mux"},
       {"HPRCOM",NULL,"Rright HP COM"},
    };

    静态连接结构snd_so_dapm_route intercon_3007[]={
       /* D类输出*/
       {"Left Class-D Out (左侧D类输出)",NULL,"Left Line Out (左侧线路输出)"},
       {"Right Class-D Out (右D类输出)",NULL,"Left Line Out (左线输出)"},
       {"SPOP",NULL,"左D类输出"},
       {"SPOM",NULL,"右D类输出"},
    };

    静态内部aic3x_add_widgets(struct snd_soc_codec *codec)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       struct snd_soc_dapm_context *dapm =&codec->dapm;

       snd_so_dapm_new_controls (dapm,aic3x_dapm_widget,
                 array_size (aic3x_dapm_widget);

       /*设置音频路径互连*/
       snd_so_dapm_add_routes (dapm,intercon,array_size (intercon));

       如果(aic3x->model == AIC3X_model_3007){
          snd_so_dapm_new_controls (dapm,aic3007_dapm_widget,
             array_size (aic3007_dapm_widget);
          Snd_so_dapm_add_routes (dapm,intercon_3007,
                   array_size (intercon_3007));
       }

       返回0;
    }

    静态内部aic3x_HW_params(struct snd_PCM_Substream*Substream,
               struct snd_pcm_hw_params *params,
               结构snd_so_dai *dai)

       struct snd_soc_pcm_runtime *RTD =子流->专用数据;
       struct snd_soc_codec *codec =RTD->codec;
       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       int codec_clk = 0,bypass_pll = 0,fsref,last_clk = 0;
       u8 data,j,r,p,pll_q, PLL_p = 1,PLL_r = 1,PLL_j = 1;
       U16 d,PLL_d = 1;
       U8 reg;
       内部clk;

       /*选择数据字长度*/
       数据= snd_so_read (codec,AIC3X_asd_INTF_CtrlB)&(~(0x3 <<4));
       开关(params_format (params)){
       案例SNDRV_PCM_FORMAT_S16_LE:
          中断;
       案例SNDRV_PCM_FORMAT_S20_3LE:
          Data |=(0x01 <<4);
          中断;
       案例SNDRV_PCM_FORMAT_S24_LE:
          Data |=(0x02 <<4);
          中断;
       案例SNDRV_PCM_FORMAT_S32_LE:
          Data |=(0x03 <<4);
          中断;
       }
       Snd_SOC_WRITE (编解码器,AIC3X_ASD_INTEL_CtrlB,数据);

       /* Fsref可以是4.41万或4.8万 */
       fsref =(params_rate (params)% 1.1025万 == 0)? 4.41万:4.8万;

       /*尝试为Q查找一个值,它允许我们绕过PLL和
       *直接生成COCODEC _CLK。 */
       对于(PLL_q = 2;PLL_q < 18;PLL_q++)
          如果(aic3x->SYSCLK /(128 * PLL_q)== fsref){
             Bypass_PLL = 1;
             中断;
          }

       如果(Bypass_PLL){
          PLL_q &= 0xF;
          Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,PLL_q << PLLQ_SHIFT);
          Snd_SOC_WRITE (CODEC,AIC3X_GPIOB_REG,CODEC_CLKIN_CLKDIV);
          /*如果已绕过PLL,则禁用PLL */
          REG = Snd_SOC_READ (编码解码器,AIC3X_PLL_PROGA_REG);
          Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,REG &~PLL_ENABLE);

       }其他{
          Snd_SOC_WRITE (CODEC,AIC3X_GPIOB_REG,COCODE_CLKIN_PLLDIV);
          /*使用PLL时启用PLL */
          REG = Snd_SOC_READ (编码解码器,AIC3X_PLL_PROGA_REG);
          Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,REG | PLL_ENABLE);
       }

       /*将左DAC路由至左通道输入和
       *右DAC至右通道输入*/
       数据=(LDAC2LCH | RDAC2RCH);
       数据||(fsref == 4.41万)? FSREF_4.41万:FSREF_4.8万;
       IF (params_rate (params)>= 6.4万)
          Data |= DUAL_RATE_MODE;
       Snd_SOC_WRITE (CODEC,AIC3X_CODCOD_DATAATH_REG,DATA);

       /*编解码器采样率选择*/
       数据=(fsref * 20)/ params_rate (params);
       如果(params_rate (params)< 6.4万)
          数据/= 2;
       数据/= 5;
       数据-=2;
       Data |=(data << 4);
       Snd_SOC_WRITE (编解码器,AIC3X_SAMPLE_RATE_SEL_REG,数据);

       IF (Bypass_PLL)
          返回0;

       /*使用PLL计算最近的j,d,r和p的适当设置
       *一人获胜。 先尝试d=0,然后尝试d!=0。
       * j的约束根据数据表。
       * SYSCLK除以1000,以防止整数溢出。
       */

       codec_clk =(2048 * fsref)/(aic3x->SYSCLK / 1000);

       (r = 1;r <= 16;r++)
          对于(p = 1;p <= 8;p++){
             对于(j = 4;j <= 55;j++){
                /*这实际上是1000*((j+(d/10000)*r)/p</s>1万
                *必须转换术语才能获得
                *除以1万;此处d = 0
                */
                int tmp_clk =(1000 * j * r)/ p;

                /*检查该值是否接近
                *我们以前吃过的最好的
                */
                如果(abs(codec_clk - tmp_clk)<
                   abs (codec_clk - last_clk){
                   PLL_j = j;PLL_d = 0;
                   PLL_r = r;PLL_p = p;
                   last_clk = tmp_clk;
                }

                /*完全匹配的提前退出*/
                IF (tmp_clk == codec_clk)
                   找到goto;
             }
          }

       /*尝试d != 0*/
       对于(p = 1;p <= 8;p++){
          j = codec_clk * p / 1000;

          如果(j < 4 || j > 11)
             继续;

          /*此处不要使用codec_clk,因为我们会失去精度*/
          d =(2048 * p * fsref)- j * aic3x->SYSCLK)
             * 100 /(aic3x->SYSCLK/100);

          CLK =(1万 * j + d)/(10 * p);

          /*检查该值是否接近最佳值
          *我们以前的*/
          如果(abs (codec_clk - clk)< abs (codec_clk - last_clk)){
             PLL_j = j;PLL_d = d;PLL_r = 1;PLL_p = p;
             last_clk = clk;
          }

          /*完全匹配的提前退出*/
          IF (clk == codec_clk)
             找到goto;
       }

       如果(last_clk == 0){
          printk (Kern_ERR "%s":无法设置PLL\n",__func__);
          返回-EINVAL;
       }

    找到:
       数据= SND_SOC_READ (CODEC,AIC3X_PLL_PROGA_REG)&~PLP_MASK;
       Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,
               数据|(PLL_p << PLLP_SHIFT));
       Snd_SOC_WRITE (编解码器,AIC3X_OVRF_STATUS_AND_PLLR_REG,
               PLL_r << PLLR_SHIFT);
       Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGB_REG,PLL_j << PLLJ_SHIFT);
       Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGC_REG,
               (PLL_d >> 6)<< PLLD_MSB_SHIFT);
       Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGD_REG,
               (PLL_d和0x3F)<< PLLD_LSB_SHIFT);

       返回0;
    }

    静态内部aic3x_mute (结构snd_so_dai *dai,int静音)

       struct snd_soc_codec *codec = dai -> codec;
       u8 LDAC_reg = snd_so_read (codec,LDAC_VOL)&~mute_on;
       U8 RDAC_reg = snd_so_read (codec,RDAC_VOL)&~mute_on;

       如果(静音){
          Snd_SOC_WRITE (CODEC,LDAC_VOL,LDAC_reg | MUTE_ON);
          Snd_SOC_WRITE (编解码器,RDAC_VOL,RDAC_reg | MUE_ON);
       }其他{
          Snd_SOC_WRITE (CODEC,LDAC_VOL,LDAC_reg);
          Snd_SOC_WRITE (编解码器,RDAC_VOL,RDAC_reg);
       }

       返回0;
    }

    静态内部aic3x_set_dae_SYSCLK(struct snd_soc_dai *codec_dai,
                int clk_id,无符号int freq,int dir)

       struct snd_soc_codec *codec = codec_dai -> codec;
       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);

       aic3x->SYSCLK =频率;
       返回0;
    }

    静态int aic3x_set_dae_fmt(struct snd_soc_dai *codec_dai,
                 无符号int fmt)

       struct snd_soc_codec *codec = codec_dai -> codec;
       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       u8 iface_areg,iface_breg;
       Int Delay (内部延迟)=0;

       iface_areg = snd_so_read (codec,AIC3X_asd_INTF_CtrlA)和0x3f;
       iface_breg = snd_so_read (codec,AIC3X_asd_INTF_CtrlB)和0x3f;

       /*设置主/从音频接口*/
       开关(fmt & snd_so_daIFmt_master_mask){
       案例Snd_SOC_DAIFMT_CBM_CFM:
          aic3x->master = 1;
          iface_Areg || bit_CLK_master | WORD_CLK_MASTER;
          中断;
       案例Snd_SOC_DAIFMT_CBS_CFS:
          aic3x->master = 0;
          iface_Areg &=~(bit_CLK_master | WORD_CLK_MASTER);
          中断;
       默认:
          返回-EINVAL;
       }

       /*
       *匹配接口格式和信号极性
       *是固定的
       */
       开关(fmt &(snd_so_DAIFMT_format_mask |)
                Snd_SOC_DAIFMT_INV_MASK)){
       案例(snd_so_DAIFMT_I2S | snd_so_DAIFMT_NB_NF):
          中断;
       案例(snd_so_DAIFMT_DSP_A | snd_so_DAIFMT_IB_NF):
          延迟= 1;
       案例(SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
          iface_breg ||(0x01 << 6);
          中断;
       案例(SND_SOC_DAIFMT_RIGHT _J | SND_SOC_DAIFMT_NB_NF):
          iface_breg ||(0x02 <<6);
          中断;
       案例(SND_SOC_DAIFMT_LEFT _J | SND_SOC_DAIFMT_NB_NF):
          iface_breg ||(0x03 <<6);
          中断;
       默认:
          返回-EINVAL;
       }

       /*设置iface */
       Snd_SOC_WRITE (编解码器,AIC3X_ASD_INTF_CtrlA,iface_Areg);
       Snd_SOC_WRITE (编解码器,AIC3X_ASD_INTF_CtrlB,iface_breg);
       Snd_SOC_WRITE (编解码器,AIC3X_ASD_INTEL_CtrlC,延迟);

       返回0;
    }

    静态int aic3x_init_3007 (结构snd_soc_codec *codec)

       u8 tmp1,tmp2,*cache = codec->reg_cache;

       /*
       *不需要缓存对未记录页面0xD的写入,但是
       *必须保留相应的第0页寄存器缓存条目
       */
       tmp1 =缓存[0xD];
       tmp2 =缓存[0x8];
       /* D类扬声器驱动程序初始化;数据表第46页*/
       Snd_SOC_WRITE (编解码器,AIC3X_PAGE_SELECT,0x0D);
       Snd_SOC_WRITE (编解码器,0xD,0x0D);
       Snd_SOC_WRITE (编解码器,0x8,0x5C);
       Snd_SOC_WRITE (编解码器,0x8,0x5D);
       Snd_SOC_WRITE (编解码器,0x8,0x5C);
       Snd_SOC_WRITE (编解码器,AIC3X_PAGE_SELECT,0x00);
       cache[0xD]= tmp1;
       cache[0x8]= tmp2;

       返回0;
    }

    静态int aic3x_reguler_event (struct notifier_block *NB,
                unsigned long事件,void *data)

       结构aic3x_dable_NB *disable_NB =
          容器_的(NB,结构aic3x_disable_NB,NB);
       struct aic3x_priv*aic3x = disable_nb->aic3x;

       如果(event & reguler_event_disable){
          /*
          *将编解码器置于重置状态,并要求至少同步一个高速缓存
          *的耗材已禁用
          */
          如果(gPIO_is_valid (aic3x->gPIO_RESET))
             gPIO_SET_VALUE (aic3x->gPIO_RESET,0);
          aic3x->codec->cache_sync = 1;
       }

       返回0;
    }

    静态内部aic3x_set_power (结构snd_so_codec *编解码器,int power)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       INT I,RET;
       u8 *cache = codec->reg_cache;

       如果(电源){
          RET =电脑控制器批量启用(array_size (aic3x ->耗材),
                      aic3x->用品);
          如果(转台)
             转至外出;
          aic3x->功率= 1;
          /*
          *只有在某些情况下才需要重置释放和高速缓存同步
          *耗材已关闭或存在缓存写入
          */
          如果(!codec->cache_sync)
             转至外出;

          如果(gPIO_is_valid (aic3x->gPIO_RESET)){
             Udelay(1);
             gPIO_SET_VALUE (aic3x->gPIO_RESET,1);
          }

          /*将reg_cache与硬件同步*/
          codec->cache_only =0;
          对于(I = AIC3X_SAMPLE_RATE_SEL_REG;I < array_size (aic3x_reg);I++)
             snd_so_write (codec,i,cache[i]);
          如果(aic3x->model == AIC3X_model_3007)
             aic3x_init_3007 (编解码器);
          codec->cache_sync = 0;
       }其他{
          /*
          *对该编解码器实例执行软重置以清除
          *电源调节器可能出现VDD泄漏电流
          *保持开启
          */
          Snd_SOC_WRITE (编解码器,AIC3X_RESET,soft_reset);
          codec->cache_sync = 1;
          aic3x->功率= 0;
          /*当偏置关闭*/时,不需要HW写入
          codec->cache_only = 1;
          RET =电脑控制器批量禁用(array_size (aic3x ->耗材),
                       aic3x->用品);
          /*如果电脑控制器禁用,则启用高速缓存同步
          *事件不是触发器。
          *待办事宜:稍后重新访问以修复
          */
          codec->cache_sync = 1;
       }
    输出:
       返回台;
    }

    静态内部aic3x_set_bias级别(结构snd_so_codec *codec,
                枚举snd_so_bas_level级别)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       U8 reg;

       开关(级别){
       案例Snd_SOC_BIAS-ON:
          中断;
       案例Snd_SOC_BIAS-PREPARE:
          IF (codec->dapm.bias级别== snd_so_bias待机&&)
             aic3x->master){
             /*启用PLL */
             REG = Snd_SOC_READ (编码解码器,AIC3X_PLL_PROGA_REG);
             Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,
                     REG | PLL_ENABLE);
          }
          中断;
       案例Snd_SOC_BIAS-STANDBY:
          如果(!aic3x->POWER)
             aic3x_set_power (codec,1);
          如果(codec->dapm.bias级别== snd_so_bias准备&&
             aic3x->master){
             /*禁用PLL */
             REG = Snd_SOC_READ (编码解码器,AIC3X_PLL_PROGA_REG);
             Snd_SOC_WRITE (编解码器,AIC3X_PLL_PROGA_REG,
                     REG &~PLL_ENABLE);
          }
          中断;
       案例Snd_SOC_BIAS-OFF:
          如果(aic3x->电源)
             aic3x_set_power (codec,0);
          中断;
       }
       codec->dapm.base_level =级别;

       返回0;
    }

    void aic3x_set_gPIO(struct snd_soc_codec *codec, int gPIO, int state)

       u8 reg = GPIO ? AIC3X_GPIO2_REG:AIC3X_GPIO1_REG;
       U8位= GPIO? 3:0;
       u8 val = snd_so_read (codec,reg)&~(1 <<位);
       snd_so_write (codec,reg,val |(!!state << bit));
    }
    export_symbol_GPL (aic3x_set_GPIO);

    int aic3x_GET_GPIO (struct snd_soc_codec *codec, int gpi)

       u8 reg = GPIO ? AIC3X_GPIO2_REG:AIC3X_GPIO1_REG;
       u8 val =0,位= GPIO ? 2:1;

       aic3x_read(codec, reg,&val);
       返回(val >>位)和1;
    }
    export_symbol_GPL (aic3x_GET_GPIO);

    void aic3x_set_headset_detects(struct snd_soc_codec*codec, int detect,
                int headset_debounce, int button_debounce)

       U8 val;

       Val =(Detect & AIC3X_header_detect_mask)
          << AIC3X_headset_detect_shift)|
            ((header_debounce和AIC3X_header_debounce_mask)
          << AIC3X_header_debounce_shift)|
            (button_debounce和AIC3X_button_debounce_mask)
          << AIC3X_BUTTON debounce_shift);

       IF (Detect & AIC3X_header_detect_mask)
          Val || AIC3X_headset_detect_enabled;

       Snd_SOC_WRITE (编解码器,AIC3X_header_detect_CTRL_A,val);
    }
    export_symbol_GPL (aic3x_set_headset_detection);

    Int aic3x_headset_detected(struct snd_soc_codec *codec)

       u8 val = 0;
       aic3x_read (编解码器,AIC3X_header_detect_CTRL_B,&val);
       返回(val >> 4)和1;
    }
    export_symbol_GPL (aic3x_headset_detected);

    int aic3x_button_pressed (结构snd_soc_codec *codec)

       u8 val = 0;
       aic3x_read (编解码器,AIC3X_header_detect_CTRL_B,&val);
       返回(val >> 5)和1;
    }
    export_symbol_GPL (aic3x_Button_pressed);

    #define AIC3X_RAates   SNDRV_PCM_RATE_8000_96000</s>9.6万
    #define AIC3X_formats   (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
             SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)

    静态结构snd_so_da_ops aic3x_dae_ops ={
       .hw_params   = aic3x_hw_params,
       digital_mute   = aic3x_mute,
       .set_SYSCLK   = aic3x_set_DAI_SYSCLK,
       .set_fmt   = aic3x_set_dae_fmt,
    };

    静态结构snd_soc_da_driver aic3x_dai ={
       .name ="tlv320aic3x-hifi",
       回放={
          .STREAM_NAME ="播放",
          .channels_min = 1,
          .channels_max = 2,
          .Rates = AIC3X_Rates,
          .formats = AIC3X_formats,},
       .capture ={
          .STREAM_NAME ="捕获",
          .channels_min = 1,
          .channels_max = 2,
          .Rates = AIC3X_Rates,
          .formats = AIC3X_formats,},
       ops =&aic3x_dae_ops,
       .symmetric_Rates = 1,
    };

    静态int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)

       aic3x_set_bias级别(编码解码器,snd_so_bias关闭);

       返回0;
    }

    静态int aic3x_resume (结构snd_soc_codec *codec)

       aic3x_set_bias级别(编码解码器,snd_so_bias待机);

       返回0;
    }

    /*
     *初始化AIC3X驱动程序
     *在内核中注册混音器和DSP接口
     */
    静态int aic3x_init(struct snd_soc_codec *codec)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       内部注册;

       Snd_SOC_WRITE (编解码器,AIC3X_PAGE_SELECT,PAGE0_SELECT);
       Snd_SOC_WRITE (编解码器,AIC3X_RESET,soft_reset);

       /* DAC默认音量和静音*/
       Snd_SOC_WRITE (CODEC,LDAC_VOL,DEFAULT_VOL | MUE_ON);
       Snd_SOC_WRITE (CODEC,RDAC_VOL,DEFAULT_VOL | MUE_ON);

       /* DAC到HP默认卷并路由到输出混音器*/
       Snd_SOC_WRITE (CODEC,DACL1_2_HPLOUT_VOL,DEFAULT_VOL | ROUTE_ON);
       Snd_SOC_WRITE (CODEC,DACR1_2_HPROUT_VOL,DEFAULT_VOL | ROUTE_ON);
       Snd_SOC_WRITE (CODEC,DACL1_2_HPLCOM_VOL,DEFAULT_VOL | ROUTE_ON);
       Snd_SOC_WRITE (CODEC,DACR1_2_HPRCOM_VOL,DEFAULT_VOL | ROUTE_ON);
       /* DAC至线路输出默认音量并路由至输出混音器*/
       Snd_SOC_WRITE (CODEC,DACL1_2_LLOPM_VOL,DEFAULT_VOL | ROUTE_ON);
       Snd_SOC_WRITE (CODEC,DACR1_2_RLOPM_VOL,DEFAULT_VOL | ROUTE_ON);
       /* DAC至单声道线路输出的默认音量,并路由至输出混音器*/
       Snd_SOC_WRITE (CODEC,DACL1_2_MONOLOPM_VOL,DEFAULT_VOL | ROUTE_ON);
       Snd_SOC_WRITE (CODEC,DACR1_2_MONOLOPM_VOL,DEFAULT_VOL | ROUTE_ON);

       /*取消所有输出的静音*/
       reg = snd_so_read (codec,LLOPM_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,LLOPM_CTRL,reg |取消静音);
       reg = snd_so_read (codec,RLOPM_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,RLOPM_CTRL,reg |取消静音);
       reg = snd_soc_read(codec, MONOLOPM_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,MONOLOPM_CTRL,reg |取消静音);
       reg = snd_so_read (codec,HPLOUT_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,HPLOUT_CTRL,reg |取消静音);
       REG = Snd_SOC_READ (CODEC,HPROUT_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,HPROUT_CTRL,reg |取消静音);
       reg = snd_so_read (codec,HPLCOM_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,HPLCOM_CTRL,reg |取消静音);
       reg = snd_so_read (codec,HPRCOM_CTRL);
    printk (" reg= %d  \n",reg);
       Snd_SOC_WRITE (CODEC,HPRCOM_CTRL,reg |取消静音);

       /* ADC默认音量和取消静音*/
       Snd_SOC_WRITE (CODEC,LADC_VOL,DEFAULT_Gain);
       Snd_SOC_WRITE (CODEC,RADC_VOL,DEFAULT_Gain);
       /*默认路由线路1到ADC PGA混音器*/
       Snd_SOC_WRITE (CODEC,LINE1L_2_LADC_CTRL,0x0);
       Snd_SOC_WRITE (CODEC,LINE1R_2_RADC_CTRL,0x0);

       /* PGA至HP旁路默认音量,断开输出混音器*/的连接
       Snd_SOC_WRITE (CODEC,PGAL_2_HPLOUT_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,PGAR_2_HPROUT_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,PGAL_2_HPLCOM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,PGAR_2_HPRCOM_VOL,DEFAULT_VOL);
       /* PGA至线路输出默认音量,断开输出混音器*/的连接
       Snd_SOC_WRITE (CODEC,PGAL_2_LLOPM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,PGAR_2_RLOPM_VOL,DEFAULT_VOL);
       /* PGA至Mono Line Out (线路输出)默认音量,断开与Output Mixer */(输出混音器)的连接
       Snd_SOC_WRITE (CODEC,PGAL_2_MONOLOPM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,PGAR_2_MONOLOPM_VOL,DEFAULT_VOL);

       /*线路2到HP旁路默认音量,从输出混音器*/断开连接
       Snd_SOC_WRITE (CODEC,LINE2L_2_HPLOUT_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,LINE2R_2_HPROUT_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,LINE2L_2_HPLCOM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,LINE2R_2_HPRCOM_VOL,DEFAULT_VOL);
       /* Line2 Line Out默认音量,与输出混音器断开*/
       Snd_SOC_WRITE (CODEC,LINE2L_2_LLOPM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,LINE2R_2_RLOPM_VOL,DEFAULT_VOL);
       /*线路2至Mono Out默认音量,断开与输出混音器*/的连接
       Snd_SOC_WRITE (CODEC,LINE2L_2_MONOLOPM_VOL,DEFAULT_VOL);
       Snd_SOC_WRITE (CODEC,LINE2R_2_MONOLOPM_VOL,DEFAULT_VOL);

       如果(aic3x->model == AIC3X_model_3007){
          aic3x_init_3007 (编解码器);
          Snd_SOC_WRITE (CODEC,CLASSD_CTRL,0);
       }

       返回0;
    }

    静态bool aic3x_is_shared_reset (结构aic3x_priv*aic3x)

       结构aic3x_priv*a;

       list_for _each_entry (a,&reset_list,list){
          如果(gPIO_is_valid (aic3x ->gPIO_RESET)&&
             aic3x->gPIO_reset == a->gPIO_reset)
             返回true;
       }

       返回false;
    }

    静态int aic3x_probe (结构snd_soc_codec *codec)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       Int ret,I;

       init_list_head(&aic3x->list);
       aic3x->codec =编解码器;
       codec->dapm.idle_bias = 1;

       RET = snd_so_codec_set_cache_io (codec,8,8,aic3x->control_type);
       如果(ret !=0){
          dev_err(codec->dev,"设置高速缓存I/O失败:%d\n", ret);
          返回台;
       }

       如果(gPIO_is_valid (aic3x ->gPIO_RESET)&&
          !aic3x_is_shared_reset (aic3x){
          RET = gPIO_REQUEST (aic3x->gPIO_RESET,"tlv320aic3x reset");
          如果(ret!= 0)
             转到err_gPIO;
          GPIO方向输出(aic3x->GPIO重置,0);
       }

       对于(i = 0;i < array_size (aic3x->耗材);I++)
          aic3x->supplies [I].supply = aic3x_supply_names[I];

       RET = reguler_bulate_get (codec->dev,array_size (aic3x ->耗材),
                aic3x->用品);
       如果(ret !=0){
          dev_err(codec->dev,"请求耗材失败:%d\n", ret);
          goto err_get;
       }
       用于(i = 0;i < array_size (aic3x->耗材);i ++){
          aic3x->disable_nb[i].nb.notifier_call = aic3x_reguler_event;
          aic3x->disable_nb[I].aic3x = aic3x;
          RET = reguler_register_notifier (aic3x ->耗材[I].consumer,
                       &aic3x->disable_nb[I].NB);
          如果(ret){
             dev_err(codec->dev,
                "无法请求稳压器通知程序:%d\n",
                RET);
             goto err_notif;
          }
       }

       codec->cache_only = 1;
       aic3x_init(codec);

       如果(aic3x->setup){
          /*设置GPIO功能*/
          Snd_SOC_WRITE (编解码器,AIC3X_GPIO1_REG,
                  (aic3x->setup->gPIO_func[0]和0xF)<<4);
          Snd_SOC_WRITE (编解码器,AIC3X_GPIO2_REG,
                  (aic3x->setup->gPIO_func[1]和0xF)<<4);
       }

       snd_so_add_controls (编解码器,aic3x_snd_controls,
                 array_size (aic3x_snd_controls);
       如果(aic3x->model == AIC3X_model_3007)
          snd_so_add_controls (编解码器,&aic3x_classd_amp_gain _ctrl,1);

       aic3x_add_widgets(codec);
       list_add(&aic3x->list,&reset_list);

       返回0;

    错误通知:
       同时(一--)
          reguler_unregister_notifier (aic3x ->耗材[I].consumer,
                        &aic3x->disable_nb[I].NB);
       电脑控制器批量免费(array_size (aic3x ->耗材),aic3x ->耗材);
    错误_获取:
       如果(gPIO_is_valid (aic3x ->gPIO_RESET)&&
          !aic3x_is_shared_reset (aic3x)
          GPIO免费(aic3x->GPIO重置);
    ERR_GPIO:
       返回台;
    }

    静态内部aic3x_remove(struct snd_soc_codec *codec)

       struct aic3x_priv*aic3x = snd_so_codec_get_drvdata(codec);
       int i;

       aic3x_set_bias级别(编码解码器,snd_so_bias关闭);
       list_del(&aic3x->list);
       如果(gPIO_is_valid (aic3x ->gPIO_RESET)&&
          !aic3x_is_shared_reset (aic3x){
          gPIO_SET_VALUE (aic3x->gPIO_RESET,0);
          GPIO免费(aic3x->GPIO重置);
       }
       对于(i = 0;i < array_size (aic3x->耗材);I++)
          reguler_unregister_notifier (aic3x ->耗材[I].consumer,
                        &aic3x->disable_nb[I].NB);
       电脑控制器批量免费(array_size (aic3x ->耗材),aic3x ->耗材);

       返回0;
    }

    静态结构snd_soc_codec_driver so_codec_dev_aic3x ={
       .set_bias级别= aic3x_set_bias级别,
       .reg_cache_size = array_size (aic3x_reg),
       .reg_word_size = sizeof(u8),
       .reg_cache_default = aic3x_reg,
       probe = aic3x_probe,
       .remove = aic3x_remove,
       suspend = aic3x_suspend,
       .resume = aic3x_resume,
    };

    #if defined (config_I2C)|| defined (config_I2C_module)
    /*
     * AIC3X 2线地址最多可以是4个具有设备地址的设备
     * 0x18,0x19,0x1A,0x1B
     */

    静态const结构i2c_device_id aic3x_i2c_id[]={
       {"tlv320aic3x",AIC3X_MODEL _3X },
       {"tlv320aic33",AIC3X_MODEL _33 },
       {"tlv320aic3007",AIC3X_MODEL _3007},
       {}
    };
    module_device_table (i2c,aic3x_i2c_id);

    /*
     *如果i2c图层没有如此损坏,我们可以传递这种数据
     *周围
     */
    静态int aic3x_i2c_prob(struct i2c_client *i2c,
               const结构i2c_device_id *id)

       struct aic3x_pdata *pdata = i2c->dev.platform_data;
       结构aic3x_priv*aic3x;
       Int ret (内部);

       aic3x = kzalloc(sizeof(struct aic3x_priv),gfp_kernel);
       如果(aic3x == NULL){
          dev_err(&i2c->dev,"创建专用数据失败\n");
          RETURN -ENOMEM;
       }

       aic3x->control_type = snd_so_I2C;

       I2C_SET_CLIENTDATA (i2c,aic3x);
       如果(pdata){
          aic3x->gPIO_reset = pdata->gPIO_reset;
          aic3x->setup = pdata->setup;
       }其他{
          aic3x->gPIO_RESET =-1;
       }

       aic3x->model = id->driver_data;

       RET = snd_soc_register_codec(&i2c->dev,
             &SOC_CODEC_DEV_AIC3x,&aic3x_DAI,1);
       如果(ret < 0)
          kfree (aic3x);
       返回台;
    }

    静态int aic3x_i2c_remove(struct i2c_client *client)

       snd_so_unregister_codec(&client->dev);
       kfree (i2c_GET_clientdata (client));
       返回0;
    }

    /*机器i2c编码解码器控制层*/
    静态结构i2c_driver aic3x_i2c_driver ={
       驱动程序={
          .name ="tlv320aic3x-codec",
          .owner =此模块,
       },
       probe   = aic3x_i2c_probe,
       .remove = aic3x_i2c_remove,
       .id_table = aic3x_i2c_id,
    };
    #endif

    静态int __init aic3x_modinit(void)

       Int ret =0;
    #if defined (config_I2C)|| defined (config_I2C_module)
       RET = i2c_add_driver (&aic3x_i2c_driver);
       如果(ret !=0){
          printk (Kern_ERR "注册TLV320AIC3x I2C驱动程序失败:%d\n",
                RET);
       }
    #endif
       返回台;
    }
    module_init (aic3x_modinit);

    静态void __exit aic3x_exit(void)

    #if defined (config_I2C)|| defined (config_I2C_module)
       I2C_DEL_DRIVER (&aic3x_i2c_driver);
    #endif
    }
    module_exit (aic3x_exit);

    module_description ("ASOC TLV320AIC3X编解码器驱动程序");
    模块作者("Vladimir Barinov");
    模块许可证("GPL");