📄 omap2-audio-twl4030.c
字号:
ret = audio_twl4030_write(REG_EAR_CTL, RdReg); if (ret) { line = __LINE__; goto disable_op_exit; } ret = audio_twl4030_write(REG_HS_SEL, 0x0); if (ret) { line = __LINE__; goto disable_op_exit; } ret = audio_twl4030_write(REG_HFL_CTL, 0x0); if (ret) { line = __LINE__; goto disable_op_exit; } ret = audio_twl4030_write(REG_HFR_CTL, 0x0); disable_op_exit: if (ret) printk(KERN_ERR "Disable Output Error [%d] in Line %d\n", ret, line); FN_OUT(ret); return ret;}/** * @brief twl4030_enable_input - enable the input to the correct device * Enable all the ADCs and path settings * *NOTE* This will not set the gain * Reason being that the gain setting can be done with CODEC power down * *NOTE* This should be called with codec power down * * @return 0 if success else error value<0 */static int twl4030_enable_input(void){//#if defined(CONFIG_MACH_OMAP3EVM) || defined(CONFIG_MACH_OMAP3_BEAGLE) u8 mic_en1 = 0; u8 mic_en2 = 0; u8 adc = 0; int ret = 0; u8 opt_ip = 0; int line = 0; FN_IN; DPRINTK(KERN_INFO "Enable Input 0x%x HS=0x%x MM=0x%x SM=0x%x\n", current_input, INPUT_HEADSET_MIC, INPUT_MAIN_MIC, INPUT_SUB_MIC); ret = audio_twl4030_read(REG_OPTION); if (ret < 0) goto enable_ip_exit; opt_ip = (ret & ~(BIT_OPTION_ATXL1_EN_M | BIT_OPTION_ATXR1_EN_M | BIT_OPTION_ATXL2_VTXL_EN_M | BIT_OPTION_ATXR2_VTXR_EN_M)); /* enable Aux-L and Aux-R i/p amplifiers */ opt_ip |= (BIT_OPTION_ATXL1_EN_M | BIT_OPTION_ATXR1_EN_M); /* select auxilliary inputs for audio in Left */ mic_en1 = 0x14; /* select auxilliary inputs for audio in Right */ mic_en2 = 0x14; /* power control enable */ adc = 0x0A; ret = audio_twl4030_write(REG_OPTION, opt_ip); if (ret) { line = __LINE__; goto enable_ip_exit; } ret = audio_twl4030_write(REG_ANAMICL, mic_en1); if (ret) { line = __LINE__; goto enable_ip_exit; } ret = audio_twl4030_write(REG_ANAMICR, mic_en2); if (ret) { line = __LINE__; goto enable_ip_exit; } ret = audio_twl4030_write(REG_AVADC_CTL, adc); if (ret) { line = __LINE__; goto enable_ip_exit; } /* Set off digital mics and select ADC o/p as i/p to Tx 1*/ ret = audio_twl4030_write(REG_ADCMICSEL, 0x0); if (ret) { line = __LINE__; goto enable_ip_exit; } /* set gain <= 6dB on Aux input */ ret = audio_twl4030_write(REG_ANAMIC_GAIN, 0x00); if (ret) { line = __LINE__; goto enable_ip_exit; } /* Set Tx path volume control as 12dB */ ret = audio_twl4030_write(REG_ATXL1PGA, 0x0C); ret = audio_twl4030_write(REG_ATXR1PGA, 0x0C); ret = audio_twl4030_write(REG_AVTXL2PGA, 0x0C); ret = audio_twl4030_write(REG_AVTXR2PGA, 0x0C); ret = audio_twl4030_write(REG_DIGMIXING, 0x0); /* No Karaoke */ enable_ip_exit: if (ret) printk(KERN_ERR "Error In Enable input[%d] in Line %d\n", ret, line); FN_OUT(ret); return ret;}/** * @brief twl4030_disable_input - reset all the inputs * *NOTE* This should be called with codec power down * * @return 0 if successful */static int twl4030_disable_input(void){ int ret = 0; int line = 0; FN_IN; /* lets shut up all devices */ ret = audio_twl4030_write(REG_MICBIAS_CTL, 0x0); if (ret) { line = __LINE__; goto disable_ip_exit; } ret = audio_twl4030_write(REG_ANAMICL, 0x0); if (ret) { line = __LINE__; goto disable_ip_exit; } ret = audio_twl4030_write(REG_ANAMICR, 0x0); if (ret) { line = __LINE__; goto disable_ip_exit; } ret = audio_twl4030_write(REG_AVADC_CTL, 0x0); if (ret) { line = __LINE__; goto disable_ip_exit; } ret = audio_twl4030_write(REG_ADCMICSEL, 0x0); if (ret) { line = __LINE__; goto disable_ip_exit; } ret = audio_twl4030_write(REG_DIGMIXING, 0x0); disable_ip_exit: if (ret) printk(KERN_ERR "Error in disable of input [%d] in Line %d\n", ret, line); FN_OUT(ret); return ret;}/** * @brief twl4030_select_source - set up proper source * Call me with the Codec powered down * @param flag * @param val * * @return 0 if successful */static int twl4030_select_source(int flag, int val){ int ret = 0; int temp = 0; FN_IN; switch (flag) { case DIR_OUT: /* * If more than one play device selected, * disable the device that is currently in use. */ if (hweight32(val) > 1) val &= ~twl4030_local.outsrc; /* can select multiple o/ps */ if ((val & SOUND_MASK_LINE1) == SOUND_MASK_LINE1) { temp |= OUTPUT_STEREO_HEADSET; } if ((val & SOUND_MASK_SPEAKER) == SOUND_MASK_SPEAKER) { temp |= OUTPUT_HANDS_FREE_CLASSD; } if ((val & SOUND_MASK_PHONEOUT) == SOUND_MASK_PHONEOUT) { temp |= OUTPUT_MONO_EARPIECE; } if ((val & SOUND_MASK_CD) == SOUND_MASK_CD) { temp |= OUTPUT_CARKIT; } current_output = temp; /* toggle the source */ if (!(ret = twl4030_disable_output())) { ret = twl4030_enable_output(); } if (!ret) { twl4030_local.outsrc = val; } break; case DIR_IN: /* if more than one device requested, reject the request */ if (hweight32(val) > 1) return -EINVAL; /* select multiple i/ps? */ if ((val & SOUND_MASK_LINE) == SOUND_MASK_LINE) { temp |= INPUT_HEADSET_MIC; } if ((val & SOUND_MASK_MIC) == SOUND_MASK_MIC) { temp |= INPUT_MAIN_MIC | INPUT_SUB_MIC; } if ((val & SOUND_MASK_RADIO) == SOUND_MASK_RADIO) { temp |= INPUT_AUX; } if ((val & SOUND_MASK_CD) == SOUND_MASK_CD) { temp |= INPUT_CARKIT; } current_input = temp; /* Toggle the source */ if (!(ret = twl4030_disable_input())) { ret = twl4030_enable_input(); } if (!ret) { twl4030_local.recsrc = val; } break; default: printk(KERN_WARNING PLATFORM_NAME "-" CODEC_NAME ": Wrong twl4030_selectsource flag specified\n"); ret = -EPERM; break; } if (!ret) { twl4030_local.mod_cnt++; } else { printk(KERN_ERR "Error selsrc Flag=%d,err=%d\n", flag, ret); } FN_OUT(ret); return ret;}/** * @brief twl4030_setvolume - set the gain of the requested device * * @param flag device for which the gain is to be set * @param gain_l * @param gain_r * * @return error if this was not done, else returns 0 */static int twl4030_setvolume(int flag, u8 gain_l, u8 gain_r){ int ret = 0; FN_IN; if ((gain_l > AUDIO_MAX_OUTPUT_VOLUME) || (gain_r > AUDIO_MAX_OUTPUT_VOLUME)) { printk(KERN_ERR "Invalid gain value %d %d\n", gain_l, gain_r); return -EPERM; } DPRINTK ("FLAG=0x%02x GAIN_L=%d[0x%02x] GAIN_R=%d[0x%2x] [R=%x]" " [W=%x] [IP=0x%x] [OP=0x%x]\n", flag, gain_l, gain_l, gain_r, gain_r, (flag >= DIR_IN) ? 1 : 0, (flag < DIR_IN) ? 1 : 0, current_input, current_output); switch (flag) { case OUTPUT_VOLUME: { /* normal volume control */ u8 fine_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / AUDIO_OUTPUT_INCREMENT); u8 fine_val_r = (unsigned char)((gain_r * COMPUTE_PRECISION) / AUDIO_OUTPUT_INCREMENT); /* Inverted power control big value is small volume */ u8 ana_val_r = (unsigned char)(((AUDIO_MAX_OUTPUT_VOLUME - gain_r) * COMPUTE_PRECISION) / ARX_APGA_INCR); u8 ana_val_l = (unsigned char)(((AUDIO_MAX_OUTPUT_VOLUME - gain_l) * COMPUTE_PRECISION) / ARX_APGA_INCR); /* default value at this time... make it ioctl ?? */ u8 coarse_val = AUDIO_DEF_COARSE_VOLUME_LEVEL; DPRINTK("outputVol gain_l requested %d, set %d\n", gain_l, fine_val_l); DPRINTK("outputVol gain_r requested %d, set %d\n", gain_r, fine_val_r); /* I2S - SDRL2 and SDRR2 */ /* Digital boost */ ret = audio_twl4030_write(REG_ARXL2PGA, coarse_val << BIT_ARXL2PGA_ARXL2PGA_CGAIN | fine_val_l << BIT_ARXL2PGA_ARXL2PGA_FGAIN); if (!ret) { ret = audio_twl4030_write(REG_ARXR2PGA, coarse_val << BIT_ARXL2PGA_ARXL2PGA_CGAIN | fine_val_r << BIT_ARXR2PGA_ARXR2PGA_FGAIN); } /* Analog boost */ if (!ret) { ret = audio_twl4030_write(REG_ARXL2_APGA_CTL, BIT_ARXL2_APGA_CTL_ARXL2_PDZ_M | BIT_ARXL2_APGA_CTL_ARXL2_DA_EN_M | ana_val_l << BIT_ARXL2_APGA_CTL_ARXL2_GAIN_SET); } if (!ret) { ret = audio_twl4030_write(REG_ARXR2_APGA_CTL, BIT_ARXR2_APGA_CTL_ARXR2_PDZ_M | BIT_ARXR2_APGA_CTL_ARXR2_DA_EN_M | ana_val_r << BIT_ARXR2_APGA_CTL_ARXR2_GAIN_SET); } if (!ret) { twl4030_local.play_volume = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=play_vol=0x%x\n", twl4030_local.play_volume); } } break; case OUTPUT_STEREO_HEADSET: /* only if current output device is stereo headset */ if ((current_output & OUTPUT_STEREO_HEADSET) == OUTPUT_STEREO_HEADSET) { /* normal volume control */ u8 fine_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / NON_LIN_INCREMENT); u8 fine_val_r = (unsigned char)((gain_r * COMPUTE_PRECISION) / NON_LIN_INCREMENT); u8 value_set[NON_LIN_GAIN_MAX] = NON_LIN_VALS; /*HS_GAIN_SET */ DPRINTK("outputHS gain_l requested %d, set %d [0x%x]\n", gain_l, fine_val_l, value_set[fine_val_l]); DPRINTK("outputHS gain_r requested %d, set %d [0x%x]\n", gain_r, fine_val_r, value_set[fine_val_r]); /* Handle Mute request */ fine_val_l = (gain_l == 0) ? 0 : value_set[fine_val_l]; fine_val_r = (gain_r == 0) ? 0 : value_set[fine_val_r]; ret = audio_twl4030_write(REG_HS_GAIN_SET, (fine_val_l << BIT_HS_GAIN_SET_HSL_GAIN) | (fine_val_r << BIT_HS_GAIN_SET_HSR_GAIN)); if (!ret) { twl4030_local.hset = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=hset=0x%x\n", twl4030_local.hset); } } break; case OUTPUT_HANDS_FREE_CLASSD: if ((current_output & OUTPUT_HANDS_FREE_CLASSD) == OUTPUT_HANDS_FREE_CLASSD) { /* NOTE: CLASSD no special gain */ twl4030_local.classd = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=classd=0x%x\n", twl4030_local.classd); } break; case OUTPUT_MONO_EARPIECE: if ((current_output & OUTPUT_MONO_EARPIECE) == OUTPUT_MONO_EARPIECE) { /* normal volume control */ u8 curr_val; u8 fine_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / NON_LIN_INCREMENT); u8 value_set[NON_LIN_GAIN_MAX] = NON_LIN_VALS; DPRINTK("outputHS gain_l requested %d, set %d [0x%x]\n", gain_l, fine_val_l, value_set[fine_val_l]); fine_val_l = (gain_l == 0) ? 0 : value_set[fine_val_l]; /*EAR_CTL */ curr_val = audio_twl4030_read(REG_EAR_CTL); curr_val &= ~BIT_EAR_CTL_EAR_GAIN_M; ret = audio_twl4030_write(REG_EAR_CTL, curr_val | (fine_val_l << BIT_EAR_CTL_EAR_GAIN)); if (!ret) { twl4030_local.ear = WRITE_LEFT_VOLUME(gain_l); DPRINTK("RESULT=ear=0x%x\n", twl4030_local.ear); } } break; case OUTPUT_SIDETONE: /* Sidetone Gain Control */ if (current_output) { ret = audio_twl4030_write(REG_VSTPGA, gain_l); if (!ret) { twl4030_local.sidetone = WRITE_LEFT_VOLUME(gain_l); DPRINTK("RESULT=sidetone=0x%x\n", twl4030_local.sidetone); } } break; case OUTPUT_CARKIT: if ((current_output & OUTPUT_CARKIT) == OUTPUT_CARKIT) { u8 curr_val; u8 fine_val_l = (unsigned char)((gain_l * COMPUTE_PRECISION) / NON_LIN_INCREMENT); u8 fine_val_r = (unsigned char)((gain_r * COMPUTE_PRECISION) / NON_LIN_INCREMENT); u8 value_set[NON_LIN_GAIN_MAX] = NON_LIN_VALS; DPRINTK("outputCkit gain_l req. %d, set %d [0x%x]\n", gain_l, fine_val_l, value_set[fine_val_l]); DPRINTK("outputCkit gain_r req. %d, set %d [0x%x]\n", gain_r, fine_val_r, value_set[fine_val_r]); fine_val_l = (gain_l == 0) ? 0 : value_set[fine_val_l]; fine_val_r = (gain_r == 0) ? 0 : value_set[fine_val_r]; /* Left gain */ curr_val = audio_twl4030_read(REG_PRECKL_CTL); curr_val &= ~BIT_PRECKL_CTL_PRECKL_GAIN_M; ret = audio_twl4030_write(REG_PRECKL_CTL, curr_val | (fine_val_l << BIT_PRECKL_CTL_PRECKL_GAIN)); if (!ret) { twl4030_local.carkit_out = WRITE_LEFT_VOLUME(gain_l); DPRINTK("RESULT=carkit=0x%x\n", twl4030_local.carkit_out); } /* Right gain */ curr_val = audio_twl4030_read(REG_PRECKR_CTL); curr_val &= ~BIT_PRECKR_CTL_PRECKR_GAIN_M; ret = audio_twl4030_write(REG_PRECKR_CTL, curr_val | (fine_val_r << BIT_PRECKR_CTL_PRECKR_GAIN)); if (!ret) { twl4030_local.carkit_out = WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=carkit_out=0x%x\n", twl4030_local.carkit_out); } } break; /* Set input volume */ case INPUT_VOLUME: { u8 set_val_l = (unsigned char) ((gain_l * COMPUTE_PRECISION) / AUDIO_INPUT_INCREMENT); u8 set_val_r = (unsigned char) ((gain_r * COMPUTE_PRECISION) / AUDIO_INPUT_INCREMENT); /* NOTE: ANAMIC gain settings is handled by a * default value */ DPRINTK("input gain_l requested %d, set %d\n", gain_l, set_val_l); DPRINTK("input gain_r requested %d, set %d\n", gain_r, set_val_r); /* I2S - TXL1 and TXR1 only */ ret = audio_twl4030_write(REG_ATXL1PGA, set_val_l << BIT_ATXL1PGA_ATXL1PGA_GAIN); if (!ret) { ret = audio_twl4030_write(REG_ATXR1PGA, set_val_r << BIT_ATXR1PGA_ATXR1PGA_GAIN); } if (!ret) { twl4030_local.rec_volume = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_r); DPRINTK("RESULT=rec_vol=0x%x\n", twl4030_local.rec_volume); } } break; case INPUT_HEADSET_MIC: if ((current_input & INPUT_HEADSET_MIC) == INPUT_HEADSET_MIC) { 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.line = WRITE_LEFT_VOLUME(gain_l) | WRITE_RIGHT_VOLUME(gain_l); DPRINTK("RESULT=line=0x%x\n", twl4030_local.line); } } break; case INPUT_MAIN_MIC:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -