📄 omap2-audio-twl4030.c
字号:
/* We do not use ALC Use ANAMIC_GAIN */ /* left volume for main mic */ if ((current_input & INPUT_MAIN_MIC) == INPUT_MAIN_MIC) { u8 set_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / MIC_AMP_INCR); int read_val = audio_twl4030_read(REG_ANAMIC_GAIN); if (read_val >= 0) { /* clear the left vol entry */ read_val &= ~(BIT_ANAMIC_GAIN_MICAMPL_GAIN_M); read_val |= set_val_l << BIT_ANAMIC_GAIN_MICAMPL_GAIN; ret = audio_twl4030_write(REG_ANAMIC_GAIN, (u8) read_val); if (!ret) { twl4030_local.mic = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(twl4030_local. mic); DPRINTK("RESULT=mic (main)=0x%x\n", twl4030_local.mic); } } } break; case INPUT_SUB_MIC: /* We do not use ALC */ /* right volume for submic */ if ((current_input & INPUT_SUB_MIC) == INPUT_SUB_MIC) { u8 set_val_r = (unsigned char)((gain_r * COMPUTE_PRECISION) / MIC_AMP_INCR); int read_val = audio_twl4030_read(REG_ANAMIC_GAIN); if (read_val >= 0) { /* clear the right vol entry */ read_val &= ~(BIT_ANAMIC_GAIN_MICAMPR_GAIN_M); read_val |= set_val_r << BIT_ANAMIC_GAIN_MICAMPR_GAIN; ret = audio_twl4030_write(REG_ANAMIC_GAIN, (u8) read_val); if (!ret) { twl4030_local.mic = WRITE_LEFT_VOLUME(twl4030_local. mic) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=mic (sub)=0x%x\n", twl4030_local.mic); } } } break; case INPUT_AUX: if ((current_input & INPUT_AUX) == INPUT_AUX) { u8 set_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / MIC_AMP_INCR); u8 set_val_r = (unsigned char)((gain_r * COMPUTE_PRECISION) / MIC_AMP_INCR); DPRINTK("anamic gain_l requested %d, set %d\n", gain_l, set_val_l); DPRINTK("anamic gain_r requested %d, set %d\n", gain_r, set_val_r); /* ANAMIC_GAIN */ ret = audio_twl4030_write(REG_ANAMIC_GAIN, (set_val_l << BIT_ANAMIC_GAIN_MICAMPL_GAIN) | (set_val_r << BIT_ANAMIC_GAIN_MICAMPR_GAIN)); if (!ret) { twl4030_local.aux = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=aux=0x%x\n", twl4030_local.aux); } } break; case INPUT_CARKIT: if ((current_input & INPUT_CARKIT) == INPUT_CARKIT) { u8 set_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / MIC_AMP_INCR); DPRINTK("anamic gain_l requested %d, set %d\n", gain_l, set_val_l); /* ANAMIC_GAIN */ ret = audio_twl4030_write(REG_ANAMIC_GAIN, set_val_l << BIT_ANAMIC_GAIN_MICAMPL_GAIN); if (!ret) { twl4030_local.carkit_in = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_l); DPRINTK("RESULT=carkit_in=0x%x\n", twl4030_local.carkit_in); } } break; default: printk(KERN_WARNING PLATFORM_NAME "-" CODEC_NAME ": Wrong twl4030_setvolume flag specified\n"); ret = -EPERM; break; } if (!ret) { twl4030_local.mod_cnt++; } FN_OUT(0); return ret;}/** * @brief twl4030_codec_conf_data_path - Configure the codec's data path * * @return 0 if successful */static int twl4030_codec_conf_data_path(void){ u8 codec_data_width = 0; u8 codec_mode = 0; /* Check sample width */ if (current_bitspersample == AUDIO_SAMPLE_DATA_WIDTH_16) { codec_data_width = AUDIO_DATA_WIDTH_16SAMPLE_16DATA; } else if (current_bitspersample == AUDIO_SAMPLE_DATA_WIDTH_24) { codec_data_width = AUDIO_DATA_WIDTH_32SAMPLE_24DATA; } else { printk(KERN_ERR "Unknown sample width %d\n", current_bitspersample); return -EPERM; } /* No Need to set BIT_AUDIO_IF_CLK256FS_EN_M -not using it as CLKS!! */ /* configure the audio IF of codec- Application Mode */ codec_mode = (codec_data_width << BIT_AUDIO_IF_DATA_WIDTH) | (AUDIO_DATA_FORMAT_I2S << BIT_AUDIO_IF_AIF_FORMAT) | BIT_AUDIO_IF_AIF_EN_M; return audio_twl4030_write(REG_AUDIO_IF, codec_mode);}/** * @brief twl4030_conf_data_interface * *NOTE* Call only from dsp device * * @return 0 if successful */static int twl4030_conf_data_interface(void){ int ret = 0; int line = 0; int frame_length1 = OMAP2_MCBSP_FRAMELEN_2; int word_length1 = OMAP2_MCBSP_WORDLEN_32; int frame_polarity = OMAP2_MCBSP_FS_ACTIVE_LOW; int skip_alt = OMAP2_MCBSP_SKIP_NONE; FN_IN; /* Check sample width */ if (current_bitspersample == AUDIO_SAMPLE_DATA_WIDTH_16) { if (current_stereomode == STEREO_MODE) { frame_polarity = OMAP2_MCBSP_FS_ACTIVE_HIGH; } else { /* mono Mode */ /* use 16 bits dma even though 32 bit width */ word_length1 = OMAP2_MCBSP_WORDLEN_16; } /* 1 word */ frame_length1 = OMAP2_MCBSP_FRAMELEN_1; } else if (current_bitspersample == AUDIO_SAMPLE_DATA_WIDTH_24) { if (current_stereomode == MONO_MODE) { /* mono Mode */ /* use 32 bits dma and do doubleindex */ skip_alt = OMAP2_MCBSP_SKIP_SECOND; } /* 2 words */ frame_length1 = OMAP2_MCBSP_FRAMELEN_2; } else { printk(KERN_ERR "Unknown sample width %d\n", current_bitspersample); return -EPERM; } /* reset the McBSP registers so that we can * configure it */ if (unlikely(ret = omap2_mcbsp_interface_reset(AUDIO_MCBSP))) { printk(KERN_ERR "conf_data Reset for MCBSP Failed[%d]\n", ret); /* Dont care abt result */ return ret; } /* setup the new params */ plat_mcbsp_config.fs_clk_pol = frame_polarity; plat_mcbsp_config.tx_polarity = frame_polarity; plat_mcbsp_config.rx_polarity = frame_polarity; ret = omap2_mcbsp_set_srg(AUDIO_MCBSP, OMAP2_MCBSP_SRG_DISABLE); if (unlikely(ret != 0)) { line = __LINE__; goto mcbsp_config_exit; } ret = omap2_mcbsp_set_fsg(AUDIO_MCBSP, OMAP2_MCBSP_FSG_DISABLE); if (unlikely(ret != 0)) { line = __LINE__; goto mcbsp_config_exit; } DPRINTK("mcbsp_id=%d samplerate=%ld," "bits=%d clk_src=%d clk=%d, sync=%d pol=%d\n", AUDIO_MCBSP, audio_samplerate, current_bitspersample, plat_mcbsp_config.srg_clk_src, 1, plat_mcbsp_config.srg_clk_sync, plat_mcbsp_config.srg_clk_pol); /* Set the sample rate in mcbsp */ /* PRCM Clock used - dont care abt clock - mcbsp, find it out */ ret = omap2_mcbsp_srg_cfg(AUDIO_MCBSP, audio_samplerate, current_bitspersample, plat_mcbsp_config.srg_clk_src, 1, plat_mcbsp_config.srg_clk_sync, plat_mcbsp_config.srg_clk_pol); if (unlikely(ret < 0)) { line = __LINE__; goto mcbsp_config_exit; } /* Setup the framesync clocks */ DPRINTK("fsync cfg rxsrc=%d, txsrc=%d tx_pol=%d rx_pol=%d " "period=%d pulsewidth=%d\n", plat_mcbsp_config.tx_clk_src, plat_mcbsp_config.rx_clk_src, plat_mcbsp_config.tx_polarity, plat_mcbsp_config.rx_polarity, current_bitspersample * 2 - 1, current_bitspersample - 1); ret = omap2_mcbsp_fsync_cfg(AUDIO_MCBSP, plat_mcbsp_config.tx_clk_src, plat_mcbsp_config.rx_clk_src, plat_mcbsp_config.tx_polarity, plat_mcbsp_config.rx_polarity, 0, 0, 0); if (unlikely(ret != 0)) { line = __LINE__; goto mcbsp_config_exit; } DPRINTK("IIItx_pol=%d, %d\n", plat_mcbsp_config.tx_clk_pol, plat_mcbsp_config.rx_clk_pol); ret = omap2_mcbsp_txclk_cfg(AUDIO_MCBSP, plat_mcbsp_config.tx_ip_clk, plat_mcbsp_config.tx_clk_pol); if (unlikely(ret != 0)) { line = __LINE__; goto mcbsp_config_exit; } ret = omap2_mcbsp_rxclk_cfg(AUDIO_MCBSP, plat_mcbsp_config.rx_ip_clk, plat_mcbsp_config.rx_clk_pol); if (unlikely(ret != 0)) { line = __LINE__; goto mcbsp_config_exit; } mcbsp_config_exit: if (unlikely(ret != 0)) { printk(KERN_ERR "Unable to configure Mcbsp ret=%d @ line %d.", ret, line); } FN_OUT(ret); return ret;}/** * @brief twl4030_set_samplerate - set the sample rate of the codec * and communication media (mcbsp) * * NOTE* Shut down the codec to change sample rate * Cannot reprogram the Codec APLL while codec is powered * * @param sample_rate - rate we wish to set * * @return 0 if successful */static int twl4030_set_samplerate(long sample_rate){ int ret = 0; int count = 0; u8 codec_mode = 0; FN_IN; /* validate if rate is proper */ for (; count < NUMBER_OF_RATES_SUPPORTED; count++) { if (valid_sample_rates[count].rate == sample_rate) { break; } } if (count >= NUMBER_OF_RATES_SUPPORTED) { printk(KERN_ERR "[%d] Unsupported sample rate!!\n", (u32) sample_rate); return -EPERM; } ret = audio_twl4030_write(REG_APLL_CTL, AUDIO_APLL_DEFAULT << BIT_APLL_CTL_APLL_INFREQ); if (ret < 0) { printk(KERN_ERR "unable to Set the INFREQ %d\n", ret); return ret; } /* Configure the codec -rate */ ret = audio_twl4030_read(REG_CODEC_MODE); if (ret < 0) { printk(KERN_ERR "unable to read codec_mode %d\n", ret); return ret; } codec_mode = (u8) ret; /* clear unnecessary bits */ codec_mode &= ~(BIT_CODEC_MODE_APLL_RATE_M); codec_mode |= (valid_sample_rates[count].apll << BIT_CODEC_MODE_APLL_RATE); ret = audio_twl4030_write(REG_CODEC_MODE, codec_mode); /* program the apll */ if (!ret) { ret = audio_twl4030_write(REG_APLL_CTL, AUDIO_APLL_DEFAULT << BIT_APLL_CTL_APLL_INFREQ | BIT_APLL_CTL_APLL_EN_M); } /* change the sample rate if we are successful */ if (!ret) { audio_samplerate = sample_rate; } FN_OUT(ret); return ret;}// #ifdef CONFIG_SND_OMAP_3430DASF/** * @brief twl4030_bit_set - setup the bitsize (16 or 24bit) * * @param bit - bitsize * @param dsp -in dsp context? * * @return 0 if all goes well, else error value */static int twl4030_bit_set(int bit, int dsp){ int ret = 0; int line = 0; FN_IN; if (bit == current_bitspersample) { /* we dont need to do anything at all! */ DPRINTK ("nothing to set in Bitsize settings\n"); return 0; } /* If the data streams are active.. it is a very very bad idea to change * data transfer modes */ if (unlikely(ret = twl4030_ext_mut_on())) { printk(KERN_ERR "twl4030_ext_mut_on failed [%d]\n", ret); return ret; } DPRINTK("Bits per sample: OLD=0x%x, new=0x%x\n", current_bitspersample, bit); current_bitspersample = bit; /* toggle power of codec */ ret = twl4030_codec_tog_on(); if (ret) { line = __LINE__; goto set_bit_exit; } ret = twl4030_codec_conf_data_path(); if (ret) { line = __LINE__; goto set_bit_exit; } /* we put the codec off again while configuring mcbsp */ ret = twl4030_codec_off(); if (ret) { line = __LINE__; goto set_bit_exit; } if (dsp) { ret = twl4030_conf_data_interface(); if (ret) { line = __LINE__; goto set_bit_exit; } ret = omap2_mcbsp_set_recv_params(AUDIO_MCBSP, &(plat_mcbsp_config.rx_params)); if (ret < 0) { line = __LINE__; goto set_bit_exit; } ret = omap2_mcbsp_set_trans_params(AUDIO_MCBSP, &(plat_mcbsp_config.tx_params)); if (ret < 0) { line = __LINE__; goto set_bit_exit; } } ret = twl4030_codec_on(); if (unlikely(!ret && (ret = twl4030_ext_mut_off()))) { printk(KERN_ERR "twl4030_ext_mut_off failed [%d]\n", ret); } set_bit_exit: if (ret) { printk(KERN_ERR "Error in setting bit rate [0x%d]@%d\n", ret, line); } FN_OUT(ret); return ret;}// #endif/** * @brief twl4030_stereomode_set - setup the stereo mode * in mono mode only the LEFT data on I2S will be valid. * This is same for RX and TX. mode is common for both rx and tx * * @param mode - stereo or mono * * @param dsp - called from dsp context? * * @return 0 if success/return error code */static int twl4030_stereomode_set(int mode, int dsp){ int ret = 0; u8 dac_ctl = 0; FN_IN; if (current_stereomode == mode) { /* nothing to do at all */ DPRINTK ("nothing to do in stereomode setting\n"); return 0; } /* If the data streams are active.. it is a very very bad idea to change * data transfer modes */ if (unlikely(ret = twl4030_ext_mut_on())) { printk(KERN_ERR "twl4030_ext_mut_on failed [%d]\n", ret); return ret; } /* toggle power of codec */ ret = twl4030_codec_tog_on(); if (ret < 0) { printk(KERN_ERR "MONO/STEREO Codec set failed\n"); goto set_stereo_mode_exit; } ret = audio_twl4030_read(REG_AVDAC_CTL); if (ret < 0) { printk(KERN_ERR "did not get dac ctrl reg\n"); goto set_stereo_mode_exit; } dac_ctl = ret; current_stereomode = mode; if (current_stereomode == MONO_MODE) { dac_ctl &= ~BIT_AVDAC_CTL_ADACR2_EN_M; } else { dac_ctl |= BIT_AVDAC_CTL_ADACR2_EN_M; } ret = audio_twl4030_write(REG_AVDAC_CTL, dac_ctl); if (ret < 0) { printk(KERN_ERR "did not set dac ctrl reg\n"); goto set_stereo_mode_exit; } /* Power off codec */ ret = twl4030_codec_off(); if (ret) { printk(KERN_ERR "Unable to switch off the codec \n"); goto set_stereo_mode_exit; } /* Let the Mcbsp work its magic */ if (dsp) { ret = twl4030_conf_data_interface(); if (ret) { printk(KERN_ERR "Configure data interface failed\n"); goto set_stereo_mode_exit; } ret = omap2_mcbsp_set_recv_params(AUDIO_MCBSP, &(plat_mcbsp_config.rx_params)); if (ret < 0) { printk(KERN_ERR "MONO/STEREO RX params failed"); goto set_stereo_mode_exit; } ret = omap2_mcbsp_set_trans_params(AUDIO_MCBSP, &(plat_mcbsp_config.tx_params)); if (ret < 0) { printk(KERN_ERR "MONO/STEREO TX params failed"); goto set_stereo_mode_exit; } } /* Set the Mixing bit off if stereo, else set it to on */ ret = audio_twl4030_write(REG_RX_PATH_SEL, 0x00); ret = twl4030_codec_on(); if (unlikely(!ret && (ret = twl4030_ext_mut_off()))) { printk(KERN_ERR "twl4030_ext_mut_off failed [%d]\n", ret); } set_stereo_mode_exit:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -