static void rk610_delayedwork_fun(struct work_struct *work) { struct snd_soc_codec *codec = rk610_codec_codec; DBG("--------%s----------\n",__FUNCTION__); spk_ctrl_fun(GPIO_HIGH); #if OUT_CAPLESS rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); #else rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); #endif }
static int rk610_codec_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); printk("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute); if (mute) { rk610_codec_write(codec,ACCELCODEC_R17, 0xFF); //AOL rk610_codec_write(codec,ACCELCODEC_R18, 0xFF); //AOR rk610_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute //add for standby // if(!dai->capture_active) // { // rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE); // rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); // rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); // } } else { // rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down // rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE); rk610_codec_write(codec,ACCELCODEC_R17, Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL rk610_codec_write(codec,ACCELCODEC_R18, Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); rk610_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM if(rk610_codec->pa_enable_time == 0) msleep(300); #if OUT_CAPLESS rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); #else rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); #endif // schedule_delayed_work(&rk610_codec->rk610_delayed_work, 0); // rk610_codec_reg_read(); if(rk610_codec->hdmi_ndet){ if(rk610_codec->pa_enable_time == 0 ) spk_ctrl_fun(GPIO_HIGH); else if(rk610_codec->pa_enable_time > 0 && rk610_codec->pa_enable_time < 300){ spk_ctrl_fun(GPIO_HIGH); msleep(rk610_codec->pa_enable_time) ; } else if(rk610_codec->pa_enable_time >=300 && rk610_codec->pa_enable_time < 1000) msleep(rk610_codec->pa_enable_time); } } return 0; }
static int rk610_codec_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); unsigned int dai_fmt = rtd->card->dai_link[0].dai_fmt; u16 iface = rk610_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3; u16 srate = rk610_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180; int coeff; coeff = get_coeff(rk610_codec->sysclk, params_rate(params)); DBG("Enter::%s----%d rk610_codec->sysclk=%d coeff = %d\n",__FUNCTION__,__LINE__,rk610_codec->sysclk, coeff); /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: iface |= 0x0004; break; case SNDRV_PCM_FORMAT_S24_LE: iface |= 0x0008; break; case SNDRV_PCM_FORMAT_S32_LE: iface |= 0x000c; break; } DBG("Enter::%s----%d iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params)); // rk610_codec_write(codec,ACCELCODEC_R0C, 0x17); rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute //必须先将clk和EN_INT都disable掉,否则切换bclk分频值可能导致codec内部时序混乱掉, //表现出来的现象是,以后的音乐都变成了噪音,而且就算把输入codec的I2S_DATAOUT断开也一样出噪音 rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00 /* set iface & srate */ if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) iface |= ASC_INVERT_BCLK;//翻转BCLK master状态送出的少了半个时钟,导致未到最大音量的时候破音、 rk610_codec_write(codec, ACCELCODEC_R09, iface); if (coeff >= 0){ // rk610_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk); rk610_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE); } rk610_codec_write(codec,ACCELCODEC_R0B, gR0BReg); return 0; }
static void rk610_delayedwork_fun(struct work_struct *work) { struct snd_soc_codec *codec = rk610_codec_codec; struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); struct rk610_codec_platform_data *pdata= rk610_codec->pdata; DBG("--------%s----------\n",__FUNCTION__); if(!pdata->boot_depop){ #if OUT_CAPLESS rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); #else rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); #endif } spk_ctrl_fun(GPIO_HIGH); }
static int rk610_codec_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); DBG("Enter::%s----%d now_level =%d old_level = %d\n",__FUNCTION__,__LINE__,level,codec->dapm.bias_level); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* VREF, VMID=2x50k, digital enabled */ // rk610_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080); break; case SND_SOC_BIAS_STANDBY: #if RESUME_PROBLEM if(rk610_codec->rk610_workstatus == SND_SOC_DAPM_STREAM_RESUME) { DBG("rk610 is resume,have not into standby\n"); rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_NOP; break; } #endif printk("rk610 standby\n"); spk_ctrl_fun(GPIO_LOW); rk610_codec_write(codec,ACCELCODEC_R0A, ASC_CLK_DISABLE); rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE); rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); break; case SND_SOC_BIAS_OFF: printk("rk610 power off\n"); spk_ctrl_fun(GPIO_LOW); rk610_codec_write(codec,ACCELCODEC_R0A, ASC_CLK_DISABLE); rk610_codec_write(codec, ACCELCODEC_R1D, 0xFF); rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF); rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF); break; } codec->dapm.bias_level = level; return 0; }
static ssize_t RK610_PROC_write(struct file *file, const char __user *buffer, unsigned long len, void *data) { char *cookie_pot; char *p; int reg; int value; cookie_pot = (char *)vmalloc( len ); if (!cookie_pot) { return -ENOMEM; } else { if (copy_from_user( cookie_pot, buffer, len )) return -EFAULT; } switch(cookie_pot[0]) { case 'p': spk_ctrl_fun(GPIO_HIGH); break; case 'o': spk_ctrl_fun(GPIO_LOW); break; case 'r': case 'R': printk("Read reg debug\n"); if(cookie_pot[1] ==':') { strsep(&cookie_pot,":"); while((p=strsep(&cookie_pot,","))) { reg = simple_strtol(p,NULL,16); value = rk610_codec_read(rk610_codec_codec,reg); printk("wm8994_read:0x%04x = 0x%04x\n",reg,value); } printk("\n"); } else { printk("Error Read reg debug.\n"); printk("For example: echo 'r:22,23,24,25'>wm8994_ts\n"); } break; case 'w': case 'W': printk("Write reg debug\n"); if(cookie_pot[1] ==':') { strsep(&cookie_pot,":"); while((p=strsep(&cookie_pot,"="))) { reg = simple_strtol(p,NULL,16); p=strsep(&cookie_pot,","); value = simple_strtol(p,NULL,16); rk610_codec_write(rk610_codec_codec,reg,value); printk("wm8994_write:0x%04x = 0x%04x\n",reg,value); } printk("\n"); } else { printk("Error Write reg debug.\n"); printk("For example: w:22=0,23=0,24=0,25=0\n"); } break; case 'D' : printk("Dump reg\n"); rk610_codec_reg_read(); break; } return len; }
void rk610_codec_reg_set(void) { struct snd_soc_codec *codec = rk610_codec_codec; unsigned int digital_gain; unsigned int mic_vol = Volume_Input; rk610_codec_write(codec,ACCELCODEC_R1D, 0x30); rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); #ifdef USE_LPF // Route R-LPF->R-Mixer, L-LPF->L-Mixer rk610_codec_write(codec,ACCELCODEC_R15, 0xC1); #else // Route RDAC->R-Mixer, LDAC->L->Mixer rk610_codec_write(codec,ACCELCODEC_R15, 0x0C); #endif // With Cap Output, VMID ramp up slow rk610_codec_write(codec,ACCELCODEC_R1A, 0x14); mdelay(10); rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB); //LIL rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB); //LIR #ifdef USE_MIC_IN if(mic_vol > 0x07) { rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB); //Select MIC input mic_vol -= 0x07; } else rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT); //Select MIC input rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); //0x00); //use default value #else rk610_codec_write(codec,ACCELCODEC_R12, 0x4c); //Select Line input #endif rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|mic_vol); //MIC // Diable route PGA->R/L Mixer, PGA gain 0db. rk610_codec_write(codec,ACCELCODEC_R13, 0x05 | 0 << 3); rk610_codec_write(codec,ACCELCODEC_R14, 0x05 | 0 << 3); //2soft mute rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute //2set default SR and clk rk610_codec_write(codec,ACCELCODEC_R0A, ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE); gR0AReg = ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE; //2Config audio interface rk610_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_MASTER_MODE|ASC_NORMAL_BCLK); rk610_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_ENABLE|ASC_SCRAMBLE_ENABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_4); //2volume,input,output digital_gain = Volume_Output; rk610_codec_write(codec,ACCELCODEC_R05, (digital_gain >> 8) & 0xFF); rk610_codec_write(codec,ACCELCODEC_R06, digital_gain & 0xFF); rk610_codec_write(codec,ACCELCODEC_R07, (digital_gain >> 8) & 0xFF); rk610_codec_write(codec,ACCELCODEC_R08, digital_gain & 0xFF); rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_ENABLE|ASC_INT_ENABLE); gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE; //ASC_DEC_DISABLE|ASC_INT_ENABLE; // #if OUT_CAPLESS // rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE); // #else // rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE); // #endif }
static int rk610_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); u16 iface = 0; spk_ctrl_fun(GPIO_LOW); rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: iface = 0x0040; break; case SND_SOC_DAIFMT_CBS_CFS: iface = 0x0000; break; default: return -EINVAL; } /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: iface |= 0x0002; break; case SND_SOC_DAIFMT_RIGHT_J: break; case SND_SOC_DAIFMT_LEFT_J: iface |= 0x0001; break; case SND_SOC_DAIFMT_DSP_A: iface |= 0x0003; break; case SND_SOC_DAIFMT_DSP_B: iface |= 0x0013; break; default: return -EINVAL; } /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_IF: iface |= 0x0090; break; case SND_SOC_DAIFMT_IB_NF: iface |= 0x0080; break; case SND_SOC_DAIFMT_NB_IF: iface |= 0x0010; break; default: return -EINVAL; } DBG("Enter::%s----%d iface=%x\n",__FUNCTION__,__LINE__,iface); rk610_codec_write(codec, ACCELCODEC_R09, iface); return 0; }