static void cpcap_audio_configure_output( struct cpcap_audio_state *state, struct cpcap_audio_state *previous_state) { static unsigned int prev_aud_out_data; if (is_output_changed(previous_state, state) || is_codec_changed(previous_state, state) || is_stdac_changed(previous_state, state)) { bool activate_ext_loudspeaker = false; struct cpcap_regacc reg_changes = { 0 }; cpcap_audio_set_output_amp_switches(state); activate_ext_loudspeaker = cpcap_audio_set_bits_for_speaker( state->codec_primary_speaker, state->codec_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->codec_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_primary_speaker, state->stdac_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_primary_speaker, state->ext_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); reg_changes.mask = reg_changes.value | prev_aud_out_data; prev_aud_out_data = reg_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, reg_changes.value, reg_changes.mask); } }
void cpcap_audio_set_audio_state(struct cpcap_audio_state *state) { struct cpcap_audio_state *previous_state = &previous_state_struct; if (state->codec_mute == CPCAP_AUDIO_CODEC_BYPASS_LOOP) state->codec_mode = CPCAP_AUDIO_CODEC_ON; if (state->codec_mode == CPCAP_AUDIO_CODEC_OFF || state->codec_mode == CPCAP_AUDIO_CODEC_CLOCK_ONLY || state->rat_type == CPCAP_AUDIO_RAT_CDMA) state->codec_mute = CPCAP_AUDIO_CODEC_MUTE; else state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE; if (state->stdac_mode != CPCAP_AUDIO_STDAC_ON) state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE; else state->stdac_mute = CPCAP_AUDIO_STDAC_UNMUTE; if (state->stdac_mode == CPCAP_AUDIO_STDAC_CLOCK_ONLY) state->stdac_mode = CPCAP_AUDIO_STDAC_ON; if ((state->codec_mode != CPCAP_AUDIO_CODEC_OFF && state->codec_mode != CPCAP_AUDIO_CODEC_CLOCK_ONLY) || state->stdac_mode != CPCAP_AUDIO_STDAC_OFF || (state->codec_primary_speaker != CPCAP_AUDIO_OUT_NONE && state->codec_primary_speaker != CPCAP_AUDIO_OUT_BT_MONO) || state->stdac_primary_speaker != CPCAP_AUDIO_OUT_NONE || state->ext_primary_speaker != CPCAP_AUDIO_OUT_NONE || (state->microphone != CPCAP_AUDIO_IN_NONE && state->microphone != CPCAP_AUDIO_IN_BT_MONO)) cpcap_audio_configure_power(1); if (is_speaker_turning_off(state, previous_state)) cpcap_audio_configure_output(state, previous_state); if (is_codec_changed(state, previous_state)) { int codec_mute = state->codec_mute; state->codec_mute = CPCAP_AUDIO_CODEC_MUTE; cpcap_audio_configure_aud_mute(state, previous_state); previous_state->codec_mute = state->codec_mute; state->codec_mute = codec_mute; cpcap_audio_configure_codec(state, previous_state); } if (is_stdac_changed(state, previous_state)) { int stdac_mute = state->stdac_mute; state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE; cpcap_audio_configure_aud_mute(state, previous_state); previous_state->stdac_mute = state->stdac_mute; state->stdac_mute = stdac_mute; cpcap_audio_configure_stdac(state, previous_state); } cpcap_audio_configure_analog_source(state, previous_state); cpcap_audio_configure_input(state, previous_state); cpcap_audio_configure_input_gains(state, previous_state); cpcap_audio_configure_output(state, previous_state); cpcap_audio_configure_output_gains(state, previous_state); cpcap_audio_configure_aud_mute(state, previous_state); if ((state->codec_mode == CPCAP_AUDIO_CODEC_OFF || state->codec_mode == CPCAP_AUDIO_CODEC_CLOCK_ONLY) && state->stdac_mode == CPCAP_AUDIO_STDAC_OFF && (state->codec_primary_speaker == CPCAP_AUDIO_OUT_NONE || state->codec_primary_speaker == CPCAP_AUDIO_OUT_BT_MONO) && state->stdac_primary_speaker == CPCAP_AUDIO_OUT_NONE && state->ext_primary_speaker == CPCAP_AUDIO_OUT_NONE && (state->microphone == CPCAP_AUDIO_IN_NONE || state->microphone == CPCAP_AUDIO_IN_BT_MONO)) cpcap_audio_configure_power(0); previous_state_struct = *state; cpcap_audio_register_dump(state); }
static void cpcap_audio_configure_codec(struct cpcap_audio_state *state, struct cpcap_audio_state *previous_state) { const unsigned int CODEC_FREQ_MASK = CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1 | CPCAP_BIT_CDC_CLK2; const unsigned int CODEC_RESET_FREQ_MASK = CODEC_FREQ_MASK | CPCAP_BIT_CDC_CLOCK_TREE_RESET; static unsigned int prev_codec_data = 0x0, prev_cdai_data = 0x0; if (is_codec_changed(state, previous_state)) { unsigned int temp_codec_rate = state->codec_rate; struct cpcap_regacc cdai_changes = { 0 }; struct cpcap_regacc codec_changes = { 0 }; int codec_freq_config = 0; if (state->rat_type == CPCAP_AUDIO_RAT_CDMA) codec_freq_config = (CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1) ; /* 19.2Mhz */ else codec_freq_config = CPCAP_BIT_CDC_CLK2 ; /* 26Mhz */ /* If a codec is already in use, reset codec to initial state */ if (previous_state->codec_mode != CPCAP_AUDIO_CODEC_OFF) { codec_changes.mask = prev_codec_data | CPCAP_BIT_DF_RESET | CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); prev_codec_data = 0; previous_state->codec_mode = CPCAP_AUDIO_CODEC_OFF; } temp_codec_rate &= 0x0000000F; temp_codec_rate = temp_codec_rate << 9; switch (state->codec_mode) { case CPCAP_AUDIO_CODEC_LOOPBACK: case CPCAP_AUDIO_CODEC_ON: if (state->codec_primary_speaker != CPCAP_AUDIO_OUT_NONE && state->dai_config == CPCAP_AUDIO_DAI_CONFIG_NORMAL) { codec_changes.value |= CPCAP_BIT_CDC_EN_RX; } if (needs_cpcap_mic1(state->microphone)) codec_changes.value |= CPCAP_BIT_MIC1_CDC_EN; if (needs_cpcap_mic2(state->microphone)) codec_changes.value |= CPCAP_BIT_MIC2_CDC_EN; /* use input HPF if either mic is enabled */ if ((codec_changes.value & (CPCAP_BIT_MIC1_CDC_EN | CPCAP_BIT_MIC2_CDC_EN)) != 0) codec_changes.value |= CPCAP_BIT_AUDIHPF_0 | CPCAP_BIT_AUDIHPF_1; if(state->mic_mute == CPCAP_AUDIO_MIC_MUTE) { codec_changes.value &= ~(CPCAP_BIT_MIC1_CDC_EN | CPCAP_BIT_MIC2_CDC_EN); CPCAP_AUDIO_DEBUG_LOG("Mic Muted\n"); } /* falling through intentionally */ case CPCAP_AUDIO_CODEC_CLOCK_ONLY: codec_changes.value |= (codec_freq_config | temp_codec_rate | CPCAP_BIT_DF_RESET); cdai_changes.value |= CPCAP_BIT_CDC_CLK_EN; break; case CPCAP_AUDIO_CODEC_OFF: cdai_changes.value |= CPCAP_BIT_SMB_CDC; break; default: break; } /* Multimedia uses CLK_IN0, incall uses CLK_IN1 */ if (state->rat_type != CPCAP_AUDIO_RAT_NONE) cdai_changes.value |= CPCAP_BIT_CLK_IN_SEL; /* Bus bus config: Codec is always master*/ cdai_changes.value |= CPCAP_BIT_CDC_DIG_AUD_FS0; /*Codec uses independent PLL in normal operation*/ if (state->dai_config == CPCAP_AUDIO_DAI_CONFIG_NORMAL) cdai_changes.value |= CPCAP_BIT_CDC_PLL_SEL; if (state->rat_type == CPCAP_AUDIO_RAT_CDMA && state->codec_primary_speaker != CPCAP_AUDIO_OUT_BT_MONO) { /* CDMA BP requires I2S mode if not Bluetooth*/ cdai_changes.value |= CPCAP_BIT_CDC_DIG_AUD_FS1 | CPCAP_BIT_CLK_INV; } else if (state->rat_type != CPCAP_AUDIO_RAT_NONE) { /* CDMA BT and all UMTS requires network mode */ cdai_changes.value |= CPCAP_BIT_MIC2_TIMESLOT0; } else { if (state->dai_config == CPCAP_AUDIO_DAI_CONFIG_HIFI_DUPLEX_1) { /* duplex I2S operation on DAI1 (untested) */ cdai_changes.value |= CPCAP_BIT_DIG_AUD_IN | CPCAP_BIT_CDC_DIG_AUD_FS1 | CPCAP_BIT_CLK_INV; } if (needs_outboard_adc(state->microphone)) { /*if we're using the outboard ADC, then it * has slots 0 and 1 so cpcap must be on * 2 and 3. */ cdai_changes.value |= CPCAP_BIT_MIC1_RX_TIMESLOT1 | CPCAP_BIT_MIC2_TIMESLOT0 | CPCAP_BIT_MIC2_TIMESLOT1; } else { if (needs_cpcap_mic2(state->microphone) && !needs_cpcap_mic1(state->microphone)) { /*if we're using *only* cpcap mic2, * put it on slot0 for mono capture. * This requires mic1 be on a slot other * than 0 due to cpcap contention logic. */ cdai_changes.value |= CPCAP_BIT_MIC1_RX_TIMESLOT0; } else { /*otherwise put MIC1 on slot0 and MIC2 * on slot 1 for either MIC1 mono or * MIC1+MIC2 stereo configurations */ cdai_changes.value |= CPCAP_BIT_MIC2_TIMESLOT0; } } } /* FIRST, make sure the frequency config is right... */ logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_FREQ_MASK); /* Next, write the CDAI if it's changed */ if (prev_cdai_data != cdai_changes.value) { cdai_changes.mask = cdai_changes.value | prev_cdai_data; prev_cdai_data = cdai_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, cdai_changes.value, cdai_changes.mask); /* Clock tree change -- reset and wait */ codec_freq_config |= CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_RESET_FREQ_MASK); /* Wait for clock tree reset to complete */ mdelay(CLOCK_TREE_RESET_TIME); } /* Clear old settings */ codec_changes.mask = codec_changes.value | prev_codec_data; prev_codec_data = codec_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); } }
static void cpcap_audio_configure_output( struct cpcap_audio_state *state, struct cpcap_audio_state *prev) { static unsigned int prev_aud_out_data; bool activate_ext_loudspeaker = false; struct cpcap_regacc reg_changes = { 0 }; if (!is_output_changed(prev, state) && !is_codec_changed(prev, state) && !is_stdac_changed(prev, state)) return; cpcap_audio_set_output_amp_switches(state); activate_ext_loudspeaker = cpcap_audio_set_bits_for_speaker( state->codec_primary_speaker, state->codec_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->codec_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_primary_speaker, state->stdac_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_primary_speaker, state->ext_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); reg_changes.mask = reg_changes.value | prev_aud_out_data; prev_aud_out_data = reg_changes.value; /* Sleep for 300ms if we are getting into a call to allow the switch to * settle. If we don't do this, it causes a loud pop at the beginning * of the call. */ if (state->rat_type == CPCAP_AUDIO_RAT_CDMA && state->ext_primary_speaker != CPCAP_AUDIO_OUT_NONE && prev->ext_primary_speaker == CPCAP_AUDIO_OUT_NONE) msleep(300); logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, reg_changes.value, reg_changes.mask); }
static void cpcap_audio_configure_codec(struct cpcap_audio_state *state, struct cpcap_audio_state *prev) { unsigned int temp_codec_rate = state->codec_rate; struct cpcap_regacc cdai_changes = { 0 }; struct cpcap_regacc codec_changes = { 0 }; int codec_freq_config = 0; const unsigned int CODEC_FREQ_MASK = CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1 | CPCAP_BIT_CDC_CLK2; const unsigned int CODEC_RESET_FREQ_MASK = CODEC_FREQ_MASK | CPCAP_BIT_CDC_CLOCK_TREE_RESET; static unsigned int prev_codec_data = 0x0, prev_cdai_data = 0x0; if (!is_codec_changed(state, prev)) return; if (state->rat_type == CPCAP_AUDIO_RAT_CDMA) codec_freq_config = (CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1) ; /* 19.2Mhz */ else codec_freq_config = CPCAP_BIT_CDC_CLK2 ; /* 26Mhz */ /* If a codec is already in use, reset codec to initial state */ if (prev->codec_mode != CPCAP_AUDIO_CODEC_OFF) { codec_changes.mask = prev_codec_data | CPCAP_BIT_DF_RESET | CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); prev_codec_data = 0; prev->codec_mode = CPCAP_AUDIO_CODEC_OFF; } temp_codec_rate &= 0x0000000F; temp_codec_rate = temp_codec_rate << 9; switch (state->codec_mode) { case CPCAP_AUDIO_CODEC_LOOPBACK: case CPCAP_AUDIO_CODEC_ON: if (state->codec_primary_speaker != CPCAP_AUDIO_OUT_NONE) { codec_changes.value |= CPCAP_BIT_CDC_EN_RX; } /* Turning on the input HPF */ if (state->microphone != CPCAP_AUDIO_IN_NONE) codec_changes.value |= CPCAP_BIT_AUDIHPF_0 | CPCAP_BIT_AUDIHPF_1; #if 1 if (state->microphone != CPCAP_AUDIO_IN_NONE) { codec_changes.value |= CPCAP_BIT_MIC1_CDC_EN; codec_changes.value |= CPCAP_BIT_MIC2_CDC_EN; } #else if (state->microphone != CPCAP_AUDIO_IN_AUX_INTERNAL && state->microphone != CPCAP_AUDIO_IN_NONE) codec_changes.value |= CPCAP_BIT_MIC1_CDC_EN | CPCAP_BIT_MIC2_CDC_EN; if (state->microphone == CPCAP_AUDIO_IN_AUX_INTERNAL || is_mic_stereo(state->microphone)) codec_changes.value |= CPCAP_BIT_MIC2_CDC_EN; #endif /* falling through intentionally */ case CPCAP_AUDIO_CODEC_CLOCK_ONLY: codec_changes.value |= (codec_freq_config | temp_codec_rate | CPCAP_BIT_DF_RESET); cdai_changes.value |= CPCAP_BIT_CDC_CLK_EN; break; case CPCAP_AUDIO_CODEC_OFF: cdai_changes.value |= CPCAP_BIT_SMB_CDC; break; default: break; } /* Multimedia uses CLK_IN0, incall uses CLK_IN1 */ if (state->rat_type != CPCAP_AUDIO_RAT_NONE) cdai_changes.value |= CPCAP_BIT_CLK_IN_SEL; cdai_changes.value |= CPCAP_BIT_CDC_PLL_SEL; #if 0 cdai_changes.value |= CPCAP_BIT_DIG_AUD_IN; #endif #ifdef CODEC_IS_I2S_MODE cdai_changes.value |= CPCAP_BIT_CLK_INV; /* Setting I2S mode */ cdai_changes.value |= CPCAP_BIT_CDC_DIG_AUD_FS0 | CPCAP_BIT_CDC_DIG_AUD_FS1 | CPCAP_BIT_MIC2_TIMESLOT0; #else /* Setting CODEC mode */ /* FS: Not inverted. * Clk: Not inverted. * TS2/TS1/TS0 not set, using timeslot 0 for mic1. */ cdai_changes.value |= CPCAP_BIT_CDC_DIG_AUD_FS0; #endif /* OK, now start paranoid codec sequence */ /* FIRST, make sure the frequency config is right... */ logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_FREQ_MASK); /* Next, write the CDAI if it's changed */ if (prev_cdai_data != cdai_changes.value) { cdai_changes.mask = cdai_changes.value | prev_cdai_data; prev_cdai_data = cdai_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, cdai_changes.value, cdai_changes.mask); /* Clock tree change -- reset and wait */ codec_freq_config |= CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_RESET_FREQ_MASK); /* Wait for clock tree reset to complete */ mdelay(CLOCK_TREE_RESET_DELAY_MS); } /* Clear old settings */ codec_changes.mask = codec_changes.value | prev_codec_data; prev_codec_data = codec_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); }
static void cpcap_audio_configure_output( struct cpcap_audio_state *state, struct cpcap_audio_state *previous_state) { static unsigned int prev_aud_out_data; if (is_output_changed(previous_state, state) || is_codec_changed(previous_state, state) || is_stdac_changed(previous_state, state)) { bool activate_ext_loudspeaker = false; struct cpcap_regacc reg_changes = { 0 }; if (is_output_headset(state) && !is_output_headset(previous_state)) { /* Charge pump should be enabled first * and wait a minimum of 750 uSec * to allow for settling of the negative supply. */ logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, CPCAP_BIT_ST_HS_CP_EN, CPCAP_BIT_ST_HS_CP_EN); /* HS plug-in noise */ /*mdelay(1);*/ mdelay(200); } cpcap_audio_set_output_amp_switches(state); activate_ext_loudspeaker = cpcap_audio_set_bits_for_speaker( state->codec_primary_speaker, state->codec_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->codec_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_primary_speaker, state->stdac_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->stdac_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_primary_speaker, state->ext_primary_balance, &(reg_changes.value)); activate_ext_loudspeaker = activate_ext_loudspeaker || cpcap_audio_set_bits_for_speaker( state->ext_secondary_speaker, CPCAP_AUDIO_BALANCE_NEUTRAL, &(reg_changes.value)); reg_changes.mask = reg_changes.value | prev_aud_out_data; prev_aud_out_data = reg_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, reg_changes.value, reg_changes.mask); if (!is_output_headset(state) && is_output_headset(previous_state)) { /* When disabling HS output amp, * HS_CP should be turned off after output * amp goes down. */ mdelay(1); logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, 0, CPCAP_BIT_ST_HS_CP_EN); } } }
static void cpcap_audio_configure_codec(struct cpcap_audio_state *state, struct cpcap_audio_state *previous_state) { const unsigned int CODEC_FREQ_MASK = CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1 | CPCAP_BIT_CDC_CLK2; const unsigned int CODEC_RESET_FREQ_MASK = CODEC_FREQ_MASK | CPCAP_BIT_CDC_CLOCK_TREE_RESET; static unsigned int prev_codec_data = 0x0, prev_cdai_data = 0x0; if (is_codec_changed(state, previous_state)) { unsigned int temp_codec_rate = state->codec_rate; struct cpcap_regacc cdai_changes = { 0 }; struct cpcap_regacc codec_changes = { 0 }; int codec_freq_config = 0; if (state->rat_type == CPCAP_AUDIO_RAT_CDMA) codec_freq_config = (CPCAP_BIT_CDC_CLK0 | CPCAP_BIT_CDC_CLK1) ; /* 19.2Mhz */ else codec_freq_config = CPCAP_BIT_CDC_CLK2 ; /* 26Mhz */ /* If a codec is already in use, reset codec to initial state */ /* TODO: optimize - make less paranoid according to TI recs */ if (previous_state->codec_mode != CPCAP_AUDIO_CODEC_OFF) { codec_changes.mask = prev_codec_data | CPCAP_BIT_DF_RESET | CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); prev_codec_data = 0; previous_state->codec_mode = CPCAP_AUDIO_CODEC_OFF; } temp_codec_rate &= 0x0000000F; temp_codec_rate = temp_codec_rate << 9; switch (state->codec_mode) { case CPCAP_AUDIO_CODEC_LOOPBACK: case CPCAP_AUDIO_CODEC_ON: if (state->codec_primary_speaker != CPCAP_AUDIO_OUT_NONE) codec_changes.value |= CPCAP_BIT_CDC_EN_RX; /* Turning on the input HPF */ if (state->microphone != CPCAP_AUDIO_IN_NONE) codec_changes.value |= CPCAP_BIT_AUDIHPF_0 | CPCAP_BIT_AUDIHPF_1; if (state->microphone != CPCAP_AUDIO_IN_AUX_INTERNAL && state->microphone != CPCAP_AUDIO_IN_NONE) codec_changes.value |= CPCAP_BIT_MIC1_CDC_EN; if (state->microphone == CPCAP_AUDIO_IN_AUX_INTERNAL || is_mic_stereo(state->microphone)) codec_changes.value |= CPCAP_BIT_MIC2_CDC_EN; /* falling through intentionally */ case CPCAP_AUDIO_CODEC_CLOCK_ONLY: codec_changes.value |= (codec_freq_config | temp_codec_rate | CPCAP_BIT_DF_RESET); cdai_changes.value |= CPCAP_BIT_CDC_CLK_EN; break; case CPCAP_AUDIO_CODEC_OFF: cdai_changes.value |= CPCAP_BIT_SMB_CDC; break; default: break; } /* Multimedia uses CLK_IN0, incall uses CLK_IN1 */ if (state->rat_type != CPCAP_AUDIO_RAT_NONE) cdai_changes.value |= CPCAP_BIT_CLK_IN_SEL; /* UMTS sholes uses Network mode - 4 time slots -Codec is Master of Fsync Bclk -CODEC uses DAI0 -CODEC PLL to be used */ cdai_changes.value |= (CPCAP_BIT_CDC_DIG_AUD_FS0 | CPCAP_BIT_CDC_PLL_SEL); if ((state->rat_type == CPCAP_AUDIO_RAT_NONE) && (state->microphone == CPCAP_AUDIO_IN_AUX_INTERNAL)) cdai_changes.value |= CPCAP_BIT_MIC1_RX_TIMESLOT0; else cdai_changes.value |= CPCAP_BIT_MIC2_TIMESLOT0; /* OK, now start paranoid codec sequence */ /* TODO: optimize - make less paranoid */ /* FIRST, make sure the frequency config is right... */ logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_FREQ_MASK); /* Next, write the CDAI if it's changed */ if (prev_cdai_data != cdai_changes.value) { cdai_changes.mask = cdai_changes.value | prev_cdai_data; prev_cdai_data = cdai_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, cdai_changes.value, cdai_changes.mask); /* Clock tree change -- reset and wait */ codec_freq_config |= CPCAP_BIT_CDC_CLOCK_TREE_RESET; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_freq_config, CODEC_RESET_FREQ_MASK); /* Wait for clock tree reset to complete */ mdelay(CLOCK_TREE_RESET_TIME); } /* Clear old settings */ codec_changes.mask = codec_changes.value | prev_codec_data; prev_codec_data = codec_changes.value; logged_cpcap_write(state->cpcap, CPCAP_REG_CC, codec_changes.value, codec_changes.mask); } }
void cpcap_audio_set_audio_state(struct cpcap_audio_state *state) { struct cpcap_audio_state *previous_state = &previous_state_struct; if (state->codec_mute == CPCAP_AUDIO_CODEC_BYPASS_LOOP) state->codec_mode = CPCAP_AUDIO_CODEC_ON; if (state->codec_mode == CPCAP_AUDIO_CODEC_OFF || state->codec_mode == CPCAP_AUDIO_CODEC_CLOCK_ONLY) state->codec_mute = CPCAP_AUDIO_CODEC_MUTE; else state->codec_mute = CPCAP_AUDIO_CODEC_UNMUTE; if (state->stdac_mode != CPCAP_AUDIO_STDAC_ON) state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE; else state->stdac_mute = CPCAP_AUDIO_STDAC_UNMUTE; /* @TODO: STDAC_CLOCK_ONLY can be used when AUX_I2S is the * only speaker to save some current. AUX_I2S is to stdac * as BT_MONO is to phone codec. */ if (state->stdac_mode == CPCAP_AUDIO_STDAC_CLOCK_ONLY) state->stdac_mode = CPCAP_AUDIO_STDAC_ON; if ((state->codec_mode != CPCAP_AUDIO_CODEC_OFF && state->codec_mode != CPCAP_AUDIO_CODEC_CLOCK_ONLY) || state->stdac_mode != CPCAP_AUDIO_STDAC_OFF || (state->codec_primary_speaker != CPCAP_AUDIO_OUT_NONE && state->codec_primary_speaker != CPCAP_AUDIO_OUT_BT_MONO) || state->stdac_primary_speaker != CPCAP_AUDIO_OUT_NONE || state->ext_primary_speaker != CPCAP_AUDIO_OUT_NONE || (state->microphone != CPCAP_AUDIO_IN_NONE && state->microphone != CPCAP_AUDIO_IN_BT_MONO)) cpcap_audio_configure_power(1); if (is_speaker_turning_off(state, previous_state)) cpcap_audio_configure_output(state, previous_state); if (is_codec_changed(state, previous_state)) { int codec_mute = state->codec_mute; state->codec_mute = CPCAP_AUDIO_CODEC_MUTE; cpcap_audio_configure_aud_mute(state, previous_state); previous_state->codec_mute = state->codec_mute; state->codec_mute = codec_mute; cpcap_audio_configure_codec(state, previous_state); } if (is_stdac_changed(state, previous_state)) { int stdac_mute = state->stdac_mute; state->stdac_mute = CPCAP_AUDIO_STDAC_MUTE; cpcap_audio_configure_aud_mute(state, previous_state); previous_state->stdac_mute = state->stdac_mute; state->stdac_mute = stdac_mute; cpcap_audio_configure_stdac(state, previous_state); } cpcap_audio_configure_analog_source(state, previous_state); cpcap_audio_configure_input(state, previous_state); cpcap_audio_configure_input_gains(state, previous_state); cpcap_audio_configure_output(state, previous_state); cpcap_audio_configure_output_gains(state, previous_state); cpcap_audio_configure_aud_mute(state, previous_state); if ((state->codec_mode == CPCAP_AUDIO_CODEC_OFF || state->codec_mode == CPCAP_AUDIO_CODEC_CLOCK_ONLY) && state->stdac_mode == CPCAP_AUDIO_STDAC_OFF && (state->codec_primary_speaker == CPCAP_AUDIO_OUT_NONE || state->codec_primary_speaker == CPCAP_AUDIO_OUT_BT_MONO) && state->stdac_primary_speaker == CPCAP_AUDIO_OUT_NONE && state->ext_primary_speaker == CPCAP_AUDIO_OUT_NONE && (state->microphone == CPCAP_AUDIO_IN_NONE || state->microphone == CPCAP_AUDIO_IN_BT_MONO)) cpcap_audio_configure_power(0); previous_state_struct = *state; cpcap_audio_reguister_dump(state); }