コード例 #1
0
static void cpcap_audio_configure_output_gains(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state)
{
	if (state->output_gain != previous_state->output_gain ||
		state->fm_output_gain != previous_state->fm_output_gain ||
		state->rat_type != previous_state->rat_type) {
		struct cpcap_regacc reg_changes = { 0 };
		unsigned int temp_output_gain = state->output_gain & 0x0000000F;
		unsigned int temp_fm_gain = state->fm_output_gain & 0x0000000F;

		reg_changes.value |=
		    ((temp_output_gain << 2) | (temp_output_gain << 8));
		if (state->rat_type == CPCAP_AUDIO_RAT_CDMA) {
			/*voice gain for analog downlink -- not needed for
			 * for Droid WE (CDMA I2S downlink)*/
			reg_changes.value |= (temp_output_gain << 12);
		} else {
			reg_changes.value |= (temp_fm_gain << 12);
		}
		reg_changes.mask = 0xFF3C;

		logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC,
				reg_changes.value, reg_changes.mask);
	}
}
コード例 #2
0
static void cpcap_audio_configure_analog_source(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state)
{
	if (state->analog_source != previous_state->analog_source) {
		struct cpcap_regacc ext_changes = { 0 };
		static unsigned int prev_ext_data;
		switch (state->analog_source) {
		case CPCAP_AUDIO_ANALOG_SOURCE_STEREO:
			ext_changes.value |= CPCAP_BIT_MONO_EXT0 |
				CPCAP_BIT_PGA_IN_R_SW | CPCAP_BIT_PGA_IN_L_SW;
			break;
		case CPCAP_AUDIO_ANALOG_SOURCE_L:
			ext_changes.value |= CPCAP_BIT_MONO_EXT1 |
						CPCAP_BIT_PGA_IN_L_SW;
			break;
		case CPCAP_AUDIO_ANALOG_SOURCE_R:
			ext_changes.value |= CPCAP_BIT_MONO_EXT1 |
						CPCAP_BIT_PGA_IN_R_SW;
			break;
		default:
			break;
		}

		ext_changes.mask = ext_changes.value | prev_ext_data;

		prev_ext_data = ext_changes.value;

		logged_cpcap_write(state->cpcap, CPCAP_REG_RXEPOA,
				ext_changes.value, ext_changes.mask);
	}
}
コード例 #3
0
static void cpcap_audio_configure_aud_mute(struct cpcap_audio_state *state,
        struct cpcap_audio_state *prev_state)
{
    struct cpcap_regacc reg_changes = { 0 };
    unsigned short int value1 = 0, value2 = 0;

    if (state->codec_mute != prev_state->codec_mute) {
        value1 = cpcap_audio_get_codec_output_amp_switches(
                     prev_state->codec_primary_speaker,
                     prev_state->codec_primary_balance);

        value2 = cpcap_audio_get_codec_output_amp_switches(
                     prev_state->codec_secondary_speaker,
                     prev_state->codec_primary_balance);

        reg_changes.mask = value1 | value2 | CPCAP_BIT_CDC_SW;

        if (state->codec_mute == CPCAP_AUDIO_CODEC_UNMUTE)
            reg_changes.value = reg_changes.mask;

        logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA,
                           reg_changes.value, reg_changes.mask);
    }

    if (state->stdac_mute != prev_state->stdac_mute) {
        value1 = cpcap_audio_get_stdac_output_amp_switches(
                     prev_state->stdac_primary_speaker,
                     prev_state->stdac_primary_balance);

        value2 = cpcap_audio_get_stdac_output_amp_switches(
                     prev_state->stdac_secondary_speaker,
                     prev_state->stdac_primary_balance);

        reg_changes.mask = value1 | value2 | CPCAP_BIT_ST_DAC_SW;

        if (state->stdac_mute == CPCAP_AUDIO_STDAC_UNMUTE)
            reg_changes.value = reg_changes.mask;

        logged_cpcap_write(state->cpcap, CPCAP_REG_RXSDOA,
                           reg_changes.value, reg_changes.mask);
    }

    /*hack*/
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA,0x1e02,0x1FFF );
}
コード例 #4
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);
	}
}
コード例 #5
0
static void cpcap_audio_configure_input_gains(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *prev)
{
	if (state->input_gain != prev->input_gain) {
		struct cpcap_regacc reg_changes = { 0 };
		unsigned int temp_input_gain = state->input_gain & 0x0000001F;

		reg_changes.value |= ((temp_input_gain << 5) | temp_input_gain);

		reg_changes.mask = 0x3FF;

		logged_cpcap_write(state->cpcap, CPCAP_REG_TXMP,
				reg_changes.value, reg_changes.mask);
	}
}
コード例 #6
0
static void cpcap_audio_configure_input_gains(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state)
{
	if (state->input_gain_r != previous_state->input_gain_r ||
		state->input_gain_l != previous_state->input_gain_l) {
		struct cpcap_regacc reg_changes = { 0 };

		reg_changes.value = state->input_gain_r & 0x1F;
		reg_changes.value |= ((state->input_gain_l & 0x1F) << 5);

		reg_changes.mask = 0x3FF;

		logged_cpcap_write(state->cpcap, CPCAP_REG_TXMP,
				reg_changes.value, reg_changes.mask);
	}
}
コード例 #7
0
static void cpcap_audio_configure_input(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state) {
	static unsigned int prev_input_data = 0x0;
	struct cpcap_regacc reg_changes = { 0 };

	if (state->microphone != previous_state->microphone ||
		CODEC_LOOPBACK_CHANGED()) {

		if (state->codec_mode == CPCAP_AUDIO_CODEC_LOOPBACK)
			reg_changes.value |= CPCAP_BIT_DLM;

		if ((state->microphone & CPCAP_AUDIO_IN_DUAL_EXTERNAL) != 0) {
			reg_changes.value |= CPCAP_BIT_RX_R_ENCODE
				| CPCAP_BIT_RX_L_ENCODE;
		} else {
			/*HANDSET and HEADSET mics are mutually exclusive.
			 *if both are selected, HANDSET will win
			 */
			if ((state->microphone & CPCAP_AUDIO_IN_HANDSET) != 0) {
				reg_changes.value |= CPCAP_BIT_MB_ON1R
						| CPCAP_BIT_MIC1_MUX |
						CPCAP_BIT_MIC1_PGA_EN;
			} else if ((state->microphone &
					CPCAP_AUDIO_IN_HEADSET) != 0) {
				reg_changes.value |= CPCAP_BIT_HS_MIC_MUX
						| CPCAP_BIT_MIC1_PGA_EN;
			}

			/*NOTE an implementation quirk: SECONDARY and TERTIARY
			 * are equivalent on 2-mic hardware.
			 * This is unintentional but harmless */
			if (needs_cpcap_mic2(state->microphone)) {
				reg_changes.value |= CPCAP_BIT_MB_ON1L
						| CPCAP_BIT_MIC2_MUX |
						CPCAP_BIT_MIC2_PGA_EN;
			}
		}

		reg_changes.mask = reg_changes.value | prev_input_data;
		prev_input_data = reg_changes.value;

		logged_cpcap_write(state->cpcap, CPCAP_REG_TXI,
					reg_changes.value, reg_changes.mask);
	}
}
コード例 #8
0
static void cpcap_audio_configure_output_gains(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state)
{
	if (state->output_gain != previous_state->output_gain) {
		struct cpcap_regacc reg_changes = { 0 };
		unsigned int temp_output_gain = state->output_gain & 0x0000000F;

		reg_changes.value |=
		    ((temp_output_gain << 2) | (temp_output_gain << 8) |
		     (temp_output_gain << 12));

		reg_changes.mask = 0xFF3C;

		logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC,
				reg_changes.value, reg_changes.mask);
	}
}
コード例 #9
0
static void cpcap_audio_configure_output_gains(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *prev)
{
	if (state->output_gain != prev->output_gain) {
		struct cpcap_regacc reg_changes = { 0 };
		unsigned int temp_output_gain = state->output_gain & 0x0000000F;

		reg_changes.value |=
		    ((temp_output_gain << 2) | (temp_output_gain << 8));
		/* VOL_EXTx is disabled, it's not connected, disable to reduce
		 * noise.  If you need it, add | (temp_output_gain << 12)
		 */
		reg_changes.mask = 0xFF3C;

		logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC,
				reg_changes.value, reg_changes.mask);
	}
}
コード例 #10
0
void cpcap_audio_init(struct cpcap_audio_state *state)
{
	CPCAP_AUDIO_DEBUG_LOG("%s() called\n", __func__);

	logged_cpcap_write(state->cpcap, CPCAP_REG_CC, 0, 0xFFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, 0, 0xBFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC, 0, 0xFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_SDACDI, 0, 0x3FFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_TXI, 0, 0xFDF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_TXMP, 0, 0xFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, 0, 0x1FF);
	/* logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC, 0, 0xFFF); */
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA, 0, 0x7FF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXSDOA, 0, 0x1FFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXEPOA, 0, 0x7FFF);

	/* 	The problem which speaker noise generated
		when phone enter the suspend mode is fixed.
	*/
	logged_cpcap_write(state->cpcap, CPCAP_REG_A2LA,
		CPCAP_BIT_A2_FREE_RUN, CPCAP_BIT_A2_FREE_RUN);

#if !defined(CONFIG_MACH_SHOLEST)
	logged_cpcap_write(state->cpcap, CPCAP_REG_GPIO4,
			   CPCAP_BIT_GPIO4DIR, CPCAP_BIT_GPIO4DIR);
#endif /* !CONFIG_MACH_SHOLEST */
	audio_reg = regulator_get(NULL, "vaudio");

	if (IS_ERR(audio_reg))
		CPCAP_AUDIO_ERROR_LOG("could not get regulator for audio\n");
}
コード例 #11
0
void cpcap_audio_init(struct cpcap_audio_state *state)
{
    CPCAP_AUDIO_DEBUG_LOG("%s() called\n", __func__);

    printk("%s() level 1\n",__func__);
    logged_cpcap_write(state->cpcap, CPCAP_REG_CC, 0, 0xFFFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, 0, 0xBFFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC, 0, 0xFFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_SDACDI, 0, 0x3FFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_TXI, 0, 0xFDF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_TXMP, 0, 0xFFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, 0, 0x1FF);
    /* logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC, 0, 0xFFF); */
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA, 0, 0x7FF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXSDOA, 0, 0x1FFF);
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXEPOA, 0, 0x7FFF);

    printk("%s() level 2\n",__func__);

    if (cpcap_audio_hw_has_hs_driver() || cpcap_audio_hw_has_mic3_switch())
        logged_cpcap_write(state->cpcap, CPCAP_REG_GPIO4,
                           CPCAP_BIT_GPIO4DIR, CPCAP_BIT_GPIO4DIR);
    /*hack*/
    printk("%s() level 3\n",__func__);
    logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA,0x1e02,0x1FFF );
    audio_regu = regulator_get(NULL, "vaudio");
    printk("%s() level 4\n",__func__);
    if (IS_ERR(audio_regu))
        CPCAP_AUDIO_ERROR_LOG("could not get regulator for audio\n");
}
コード例 #12
0
static void cpcap_audio_configure_stdac(struct cpcap_audio_state *state,
				struct cpcap_audio_state *previous_state)
{
	const unsigned int SDAC_FREQ_MASK = CPCAP_BIT_ST_DAC_CLK0
		| CPCAP_BIT_ST_DAC_CLK1 | CPCAP_BIT_ST_DAC_CLK2;
	const unsigned int SDAC_RESET_FREQ_MASK = SDAC_FREQ_MASK
		| CPCAP_BIT_ST_CLOCK_TREE_RESET;
	static unsigned int prev_stdac_data, prev_sdai_data;

	if (is_stdac_changed(state, previous_state)) {
		unsigned int temp_stdac_rate = state->stdac_rate;
		struct cpcap_regacc sdai_changes = { 0 };
		struct cpcap_regacc stdac_changes = { 0 };
		int stdac_freq_config = 0;

		if (state->rat_type == CPCAP_AUDIO_RAT_CDMA)
			stdac_freq_config = (CPCAP_BIT_ST_DAC_CLK0
					| CPCAP_BIT_ST_DAC_CLK1) ; /*19.2Mhz*/
		else
			stdac_freq_config = CPCAP_BIT_ST_DAC_CLK2 ; /* 26Mhz */

		/* We need to turn off stdac before changing its settings */
		if (previous_state->stdac_mode != CPCAP_AUDIO_STDAC_OFF) {
			stdac_changes.mask = prev_stdac_data |
					CPCAP_BIT_DF_RESET_ST_DAC |
					CPCAP_BIT_ST_CLOCK_TREE_RESET;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_changes.value, stdac_changes.mask);

			prev_stdac_data = 0;
			previous_state->stdac_mode = CPCAP_AUDIO_STDAC_OFF;
		}

		temp_stdac_rate &= 0x0000000F;
		temp_stdac_rate = temp_stdac_rate << 4;

		switch (state->stdac_mode) {
		case CPCAP_AUDIO_STDAC_ON:
			stdac_changes.value |= CPCAP_BIT_ST_DAC_EN;
			/* falling through intentionally */
		case CPCAP_AUDIO_STDAC_CLOCK_ONLY:
			stdac_changes.value |= temp_stdac_rate |
						 CPCAP_BIT_DF_RESET_ST_DAC |
						 stdac_freq_config;
			sdai_changes.value |= CPCAP_BIT_ST_CLK_EN;
			break;

		case CPCAP_AUDIO_STDAC_OFF:
		default:
			break;
		}

		if (state->rat_type != CPCAP_AUDIO_RAT_NONE)
			sdai_changes.value |= CPCAP_BIT_ST_DAC_CLK_IN_SEL;

		/* -True I2S mode
		-STDAC is Master of Fsync Bclk
		-STDAC uses DAI1
		*/
#ifdef AUDIO_I2S_MODE
		sdai_changes.value |= CPCAP_BIT_DIG_AUD_IN_ST_DAC |
			CPCAP_BIT_ST_DIG_AUD_FS0 | CPCAP_BIT_ST_DIG_AUD_FS1;
#else
		sdai_changes.value |= CPCAP_BIT_ST_DIG_AUD_FS0 |
			CPCAP_BIT_DIG_AUD_IN_ST_DAC | CPCAP_BIT_ST_L_TIMESLOT0;
#endif
		/* OK, now start paranoid stdac sequence */
		/* TODO: optimize - make less paranoid */
		/* FIRST, make sure the frequency config is right... */
		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
			stdac_freq_config, SDAC_FREQ_MASK);

		/* Next, write the SDACDI if it's changed */
		if (prev_sdai_data != sdai_changes.value) {
			sdai_changes.mask = sdai_changes.value
				| prev_sdai_data;
			prev_sdai_data = sdai_changes.value;

			logged_cpcap_write(state->cpcap,
				CPCAP_REG_SDACDI, sdai_changes.value,
				sdai_changes.mask);

			/* Clock tree change -- reset and wait */
			stdac_freq_config |= CPCAP_BIT_ST_CLOCK_TREE_RESET;
			logged_cpcap_write(state->cpcap,
					CPCAP_REG_SDAC,
					stdac_freq_config,
					SDAC_RESET_FREQ_MASK);

			/* Wait for clock tree reset to complete */
			mdelay(CLOCK_TREE_RESET_TIME);
		}

		/* Clear old settings */
		stdac_changes.mask = stdac_changes.value | prev_stdac_data;
		prev_stdac_data = stdac_changes.value;

		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
			stdac_changes.value, stdac_changes.mask);
	}
}
コード例 #13
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);
	}
}
コード例 #14
0
static void cpcap_audio_configure_stdac(struct cpcap_audio_state *state,
				struct cpcap_audio_state *previous_state)
{
	const unsigned int SDAC_FREQ_MASK = CPCAP_BIT_ST_DAC_CLK0
			| CPCAP_BIT_ST_DAC_CLK1 | CPCAP_BIT_ST_DAC_CLK2;
	const unsigned int SDAC_RESET_FREQ_MASK = SDAC_FREQ_MASK
					| CPCAP_BIT_ST_CLOCK_TREE_RESET;
	static unsigned int prev_stdac_data, prev_sdai_data;

	if (is_stdac_changed(state, previous_state)) {
		unsigned int temp_stdac_rate = state->stdac_rate;
		struct cpcap_regacc sdai_changes = { 0 };
		struct cpcap_regacc stdac_changes = { 0 };

		int stdac_freq_config = 0;
		if (state->rat_type == CPCAP_AUDIO_RAT_CDMA)
			stdac_freq_config = (CPCAP_BIT_ST_DAC_CLK0
					| CPCAP_BIT_ST_DAC_CLK1) ; /*19.2Mhz*/
		else
			stdac_freq_config = CPCAP_BIT_ST_DAC_CLK2 ; /* 26Mhz */

		/* We need to turn off stdac before changing its settings */
		if (previous_state->stdac_mode != CPCAP_AUDIO_STDAC_OFF) {
			stdac_changes.mask = prev_stdac_data |
					CPCAP_BIT_DF_RESET_ST_DAC |
					CPCAP_BIT_ST_CLOCK_TREE_RESET;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_changes.value, stdac_changes.mask);

			prev_stdac_data = 0;
			previous_state->stdac_mode = CPCAP_AUDIO_STDAC_OFF;
		}

		temp_stdac_rate &= 0x0000000F;
		temp_stdac_rate = temp_stdac_rate << 4;

		switch (state->stdac_mode) {
		case CPCAP_AUDIO_STDAC_ON:
			stdac_changes.value |= CPCAP_BIT_ST_DAC_EN;
		/* falling through intentionally */
		case CPCAP_AUDIO_STDAC_CLOCK_ONLY:
			stdac_changes.value |= temp_stdac_rate |
				CPCAP_BIT_DF_RESET_ST_DAC | stdac_freq_config;
			sdai_changes.value |= CPCAP_BIT_ST_CLK_EN;
			break;

		case CPCAP_AUDIO_STDAC_OFF:
		default:
			break;
		}

		if (state->rat_type != CPCAP_AUDIO_RAT_NONE)
			sdai_changes.value |= CPCAP_BIT_ST_DAC_CLK_IN_SEL;

		if (state->dai_config == CPCAP_AUDIO_DAI_CONFIG_HIFI_DUPLEX_0) {
			/* when using DAI0, follow the codec configuration:
			 * 4-slot network, R on slot 0, L on slot 1 */
			sdai_changes.value |= CPCAP_BIT_ST_DIG_AUD_FS0
					| CPCAP_BIT_ST_L_TIMESLOT0;
		} else {
			/* -True I2S mode
			 * -STDAC is Master of Fsync Bclk
			 * -STDAC uses DAI1 */
			sdai_changes.value |= CPCAP_BIT_DIG_AUD_IN_ST_DAC
					| CPCAP_BIT_ST_DIG_AUD_FS0
					| CPCAP_BIT_ST_DIG_AUD_FS1;
		}

		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
					stdac_freq_config, SDAC_FREQ_MASK);

		/* Next, write the SDACDI if it's changed */
		if (prev_sdai_data != sdai_changes.value) {
			sdai_changes.mask = sdai_changes.value
						| prev_sdai_data;
			prev_sdai_data = sdai_changes.value;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDACDI,
					sdai_changes.value, sdai_changes.mask);

			/* Clock tree change -- reset and wait */
			stdac_freq_config |= CPCAP_BIT_ST_CLOCK_TREE_RESET;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_freq_config, SDAC_RESET_FREQ_MASK);

			/* Wait for clock tree reset to complete */
			mdelay(CLOCK_TREE_RESET_TIME);
		}

		/* Clear old settings */
		stdac_changes.mask = stdac_changes.value | prev_stdac_data;
		prev_stdac_data = stdac_changes.value;

		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
			stdac_changes.value, stdac_changes.mask);
	}
}
コード例 #15
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);
		}
	}
}
コード例 #16
0
static void cpcap_audio_set_output_amp_switches(struct cpcap_audio_state *state)
{
	static unsigned int 	codec_prev_settings = 0,
				stdac_prev_settings = 0,
				ext_prev_settings = 0;

	struct cpcap_regacc reg_changes;
	unsigned short int value1 = 0, value2 = 0;

	/* First set codec output amp switches */
	value1 = cpcap_audio_get_codec_output_amp_switches(state->
			codec_primary_speaker, state->codec_primary_balance);
	value2 = cpcap_audio_get_codec_output_amp_switches(state->
			codec_secondary_speaker, state->codec_primary_balance);

	reg_changes.mask = value1 | value2 | codec_prev_settings;
	reg_changes.value = value1 | value2;
	codec_prev_settings = reg_changes.value;

	logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA, reg_changes.value,
							reg_changes.mask);

	/* Second Stdac switches */
	value1 = cpcap_audio_get_stdac_output_amp_switches(state->
			stdac_primary_speaker, state->stdac_primary_balance);
	value2 = cpcap_audio_get_stdac_output_amp_switches(state->
			stdac_secondary_speaker, state->stdac_primary_balance);

	reg_changes.mask = value1 | value2 | stdac_prev_settings;
	reg_changes.value = value1 | value2;

	if ((state->stdac_primary_speaker == CPCAP_AUDIO_OUT_STEREO_HEADSET &&
		state->stdac_secondary_speaker == CPCAP_AUDIO_OUT_LOUDSPEAKER)
		|| (state->stdac_primary_speaker == CPCAP_AUDIO_OUT_LOUDSPEAKER
		&& state->stdac_secondary_speaker ==
						CPCAP_AUDIO_OUT_STEREO_HEADSET))
		reg_changes.value &= ~(CPCAP_BIT_MONO_DAC0 |
					CPCAP_BIT_MONO_DAC1);

	stdac_prev_settings = reg_changes.value;

	logged_cpcap_write(state->cpcap, CPCAP_REG_RXSDOA, reg_changes.value,
							reg_changes.mask);

	/* Last External source switches */
	value1 =
	    cpcap_audio_get_ext_output_amp_switches(state->
				ext_primary_speaker,
				state->ext_primary_balance);
	value2 =
	    cpcap_audio_get_ext_output_amp_switches(state->
				ext_secondary_speaker,
				state->ext_primary_balance);

	reg_changes.mask = value1 | value2 | ext_prev_settings;
	reg_changes.value = value1 | value2;
	ext_prev_settings = reg_changes.value;

	logged_cpcap_write(state->cpcap, CPCAP_REG_RXEPOA,
			reg_changes.value, reg_changes.mask);
}
コード例 #17
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);
	}
}
コード例 #18
0
void cpcap_audio_init(struct cpcap_audio_state *state)
{
	CPCAP_AUDIO_DEBUG_LOG("%s() called\n", __func__);

	logged_cpcap_write(state->cpcap, CPCAP_REG_CC, 0, 0xFFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_CDI, 0, 0xBFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC, 0, 0xFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_SDACDI, 0, 0x3FFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_TXI, 0, 0xFDF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_TXMP, 0, 0xFFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXOA, 0, 0x1FF);
	/* logged_cpcap_write(state->cpcap, CPCAP_REG_RXVC, 0, 0xFFF); */
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXCOA, 0, 0x7FF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXSDOA, 0, 0x1FFF);
	logged_cpcap_write(state->cpcap, CPCAP_REG_RXEPOA, 0, 0x7FFF);

		/* Use free running clock for amplifiers */
		logged_cpcap_write(state->cpcap, CPCAP_REG_A2LA,
			CPCAP_BIT_A2_FREE_RUN, CPCAP_BIT_A2_FREE_RUN);

	audio_reg = regulator_get(NULL, "vaudio");

	if (IS_ERR(audio_reg))
		CPCAP_AUDIO_ERROR_LOG("could not get regulator for audio\n");
}
コード例 #19
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);
}
コード例 #20
0
static void cpcap_audio_configure_input(
	struct cpcap_audio_state *state,
	struct cpcap_audio_state *previous_state) {
	static unsigned int prev_input_data = 0x0;
	struct cpcap_regacc reg_changes = { 0 };

	if (state->microphone != previous_state->microphone ||
		CODEC_LOOPBACK_CHANGED()) {

		if (state->codec_mode == CPCAP_AUDIO_CODEC_LOOPBACK)
			reg_changes.value |= CPCAP_BIT_DLM;

#if !defined(CONFIG_MACH_SHOLEST)
		if (previous_state->microphone
		    == CPCAP_AUDIO_IN_HEADSET) {
			logged_cpcap_write(state->cpcap, CPCAP_REG_GPIO4,
				     0, CPCAP_BIT_GPIO4DRV);
		}
#endif /* !CONFIG_MACH_SHOLEST */

		switch (state->microphone) {
		case CPCAP_AUDIO_IN_HANDSET:
			reg_changes.value |= CPCAP_BIT_MB_ON1R
				| CPCAP_BIT_MIC1_MUX | CPCAP_BIT_MIC1_PGA_EN;
			break;

		case CPCAP_AUDIO_IN_HEADSET:
			reg_changes.value |= CPCAP_BIT_HS_MIC_MUX
				| CPCAP_BIT_MIC1_PGA_EN;

#if !defined(CONFIG_MACH_SHOLEST)
			logged_cpcap_write(state->cpcap, CPCAP_REG_GPIO4,
					   CPCAP_BIT_GPIO4DRV,
					   CPCAP_BIT_GPIO4DRV);
#endif /* !CONFIG_MACH_SHOLEST */
			break;

		case CPCAP_AUDIO_IN_EXT_BUS:
			reg_changes.value |=  CPCAP_BIT_EMU_MIC_MUX
				| CPCAP_BIT_MIC1_PGA_EN;
			break;

		case CPCAP_AUDIO_IN_AUX_INTERNAL:
			reg_changes.value |= CPCAP_BIT_MB_ON1L
				| CPCAP_BIT_MIC2_MUX | CPCAP_BIT_MIC2_PGA_EN;
			break;

		case CPCAP_AUDIO_IN_DUAL_INTERNAL:
			reg_changes.value |= CPCAP_BIT_MB_ON1R
				| CPCAP_BIT_MIC1_MUX | CPCAP_BIT_MIC1_PGA_EN
				| CPCAP_BIT_MB_ON1L | CPCAP_BIT_MIC2_MUX
				| CPCAP_BIT_MIC2_PGA_EN;
			break;

		case CPCAP_AUDIO_IN_DUAL_EXTERNAL:
			reg_changes.value |= CPCAP_BIT_RX_R_ENCODE
				| CPCAP_BIT_RX_L_ENCODE;
			break;

		case CPCAP_AUDIO_IN_BT_MONO:
		default:
			reg_changes.value = 0;
			break;
		}

		reg_changes.mask = reg_changes.value | prev_input_data;
		prev_input_data = reg_changes.value;

		logged_cpcap_write(state->cpcap, CPCAP_REG_TXI,
			reg_changes.value, reg_changes.mask);
	}
}
コード例 #21
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);
}
コード例 #22
0
static void cpcap_audio_configure_stdac(struct cpcap_audio_state *state,
				struct cpcap_audio_state *prev)
{
	const unsigned int SDAC_FREQ_MASK = CPCAP_BIT_ST_DAC_CLK0
			| CPCAP_BIT_ST_DAC_CLK1 | CPCAP_BIT_ST_DAC_CLK2;
	const unsigned int SDAC_RESET_FREQ_MASK = SDAC_FREQ_MASK
					| CPCAP_BIT_ST_CLOCK_TREE_RESET;
	static unsigned int prev_stdac_data, prev_sdai_data;

	if (is_stdac_changed(state, prev)) {
		unsigned int temp_stdac_rate = state->stdac_rate;
		struct cpcap_regacc sdai_changes = { 0 };
		struct cpcap_regacc stdac_changes = { 0 };

		int stdac_freq_config = 0;
		if (state->rat_type == CPCAP_AUDIO_RAT_CDMA)
			stdac_freq_config = (CPCAP_BIT_ST_DAC_CLK0
					| CPCAP_BIT_ST_DAC_CLK1) ; /*19.2Mhz*/
		else
			stdac_freq_config = CPCAP_BIT_ST_DAC_CLK2 ; /* 26Mhz */

		/* We need to turn off stdac before changing its settings */
		if (prev->stdac_mode != CPCAP_AUDIO_STDAC_OFF) {
			stdac_changes.mask = prev_stdac_data |
					CPCAP_BIT_DF_RESET_ST_DAC |
					CPCAP_BIT_ST_CLOCK_TREE_RESET;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_changes.value, stdac_changes.mask);

			prev_stdac_data = 0;
			prev->stdac_mode = CPCAP_AUDIO_STDAC_OFF;
		}

		temp_stdac_rate &= 0x0000000F;
		temp_stdac_rate = temp_stdac_rate << 4;

		switch (state->stdac_mode) {
		case CPCAP_AUDIO_STDAC_ON:
			stdac_changes.value |= CPCAP_BIT_ST_DAC_EN;
		/* falling through intentionally */
		case CPCAP_AUDIO_STDAC_CLOCK_ONLY:
			stdac_changes.value |= temp_stdac_rate |
				CPCAP_BIT_DF_RESET_ST_DAC | stdac_freq_config;
			sdai_changes.value |= CPCAP_BIT_ST_CLK_EN;
			break;

		case CPCAP_AUDIO_STDAC_OFF:
		default:
			break;
		}

		if (state->rat_type != CPCAP_AUDIO_RAT_NONE)
			sdai_changes.value |= CPCAP_BIT_ST_DAC_CLK_IN_SEL;
		/* begin everest change */
		/*
		sdai_changes.value |= CPCAP_BIT_ST_DIG_AUD_FS0 |
			CPCAP_BIT_DIG_AUD_IN_ST_DAC | CPCAP_BIT_ST_L_TIMESLOT0;
		*/
		/* I2S Mode, ignore timeslots, invert bit clock */
		sdai_changes.value |= CPCAP_BIT_ST_DIG_AUD_FS0 |
			CPCAP_BIT_DIG_AUD_IN_ST_DAC |
			CPCAP_BIT_ST_DIG_AUD_FS1 | CPCAP_BIT_ST_CLK_INV;
		/* end everest change */

		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_freq_config, SDAC_FREQ_MASK);

		/* Next, write the SDACDI if it's changed */
		if (prev_sdai_data != sdai_changes.value) {
			sdai_changes.mask = sdai_changes.value
						| prev_sdai_data;
			prev_sdai_data = sdai_changes.value;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDACDI,
					sdai_changes.value, sdai_changes.mask);

			/* Clock tree change -- reset and wait */
			stdac_freq_config |= CPCAP_BIT_ST_CLOCK_TREE_RESET;

			logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
				stdac_freq_config, SDAC_RESET_FREQ_MASK);

			/* Wait for clock tree reset to complete */
			mdelay(CLOCK_TREE_RESET_DELAY_MS);
		}

		/* Clear old settings */
		stdac_changes.mask = stdac_changes.value | prev_stdac_data;
		prev_stdac_data = stdac_changes.value;

		if ((stdac_changes.value | CPCAP_BIT_ST_DAC_EN) &&
		    (state->cpcap->vendor == CPCAP_VENDOR_ST)) {
			logged_cpcap_write(state->cpcap, CPCAP_REG_TEST,
					   STM_STDAC_EN_TEST_PRE, 0xFFFF);
			logged_cpcap_write(state->cpcap, CPCAP_REG_ST_TEST1,
					   STM_STDAC_EN_ST_TEST1_PRE, 0xFFFF);
		}

		logged_cpcap_write(state->cpcap, CPCAP_REG_SDAC,
			stdac_changes.value, stdac_changes.mask);

		if ((stdac_changes.value | CPCAP_BIT_ST_DAC_EN) &&
		    (state->cpcap->vendor == CPCAP_VENDOR_ST)) {
			msleep(STM_STDAC_ACTIVATE_RAMP_TIME);
			logged_cpcap_write(state->cpcap, CPCAP_REG_ST_TEST1,
					   STM_STDAC_EN_ST_TEST1_POST, 0xFFFF);
			logged_cpcap_write(state->cpcap, CPCAP_REG_TEST,
					   STM_STDAC_EN_TEST_POST, 0xFFFF);
		}
	}
}