Example #1
0
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);
	}
}
Example #2
0
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);
}
Example #3
0
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);
	}
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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);
		}
	}
}
Example #7
0
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);
	}
}
Example #8
0
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);
}