void wcd9xxx_enable_high_perf_mode(struct snd_soc_codec *codec,
				struct wcd9xxx_clsh_cdc_data *clsh_d,
				u8 uhqa_mode, u8 req_state, bool req_type)
{
	dev_dbg(codec->dev, "%s: users fclk8 %d, fclk5 %d", __func__,
			clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
			clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);

	if (req_type == WCD9XXX_CLSAB_REQ_ENABLE) {
		clsh_d->ncp_users[NCP_FCLK_LEVEL_8]++;
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_BIAS_PA,
					WCD9XXX_A_RX_HPH_BIAS_PA__POR);
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_L_PA_CTL, 0x48);
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_R_PA_CTL, 0x48);
		if (uhqa_mode)
			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL,
						0x20, 0x00);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		wcd9xxx_enable_buck(codec, clsh_d, false);
		if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x0F, 0x08);
		snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x30, 0x30);

		/* Enable NCP and wait until settles down */
		if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01))
			usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US+10);
	} else {
		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL,
					0x20, 0x20);
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_L_PA_CTL,
					WCD9XXX_A_RX_HPH_L_PA_CTL__POR);
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_R_PA_CTL,
					WCD9XXX_A_RX_HPH_R_PA_CTL__POR);
		snd_soc_write(codec, WCD9XXX_A_RX_HPH_BIAS_PA, 0x55);
		wcd9xxx_enable_buck(codec, clsh_d, true);
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_anc_delay(codec, false);
		clsh_d->ncp_users[NCP_FCLK_LEVEL_8]--;
		if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 &&
		    clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
						0x01, 0x00);
		else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x0F, 0x05);
	}
	dev_dbg(codec->dev, "%s: leave\n", __func__);
}
Beispiel #2
0
static void wcd9xxx_clsh_state_hph_r(struct snd_soc_codec *codec,
		struct wcd9xxx_clsh_cdc_data *clsh_d,
		u8 req_state, bool is_enable)
{
	if (is_enable) {

		wcd9xxx_cfg_clsh_buck(codec);
		wcd9xxx_cfg_clsh_param_common(codec);
		wcd9xxx_cfg_clsh_param_hph(codec);
		wcd9xxx_enable_clsh_block(codec, true);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
		wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
		wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);

		dev_dbg(codec->dev, "%s: Done\n", __func__);
	} else {
		if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
					      false);
		} else {
			dev_dbg(codec->dev, "%s: stub fallback to hph_r\n",
					__func__);
		}
	}
}
static void wcd9xxx_clsh_state_hph_r(struct snd_soc_codec *codec,
		struct wcd9xxx_clsh_cdc_data *clsh_d,
		u8 req_state, bool is_enable)
{
	pr_debug("%s: enter %s, state %d, req_state %d\n", __func__,
		 is_enable ? "enable" : "disable", clsh_d->state,
		 req_state);

	if (is_enable) {
		wcd9xxx_cfg_clsh_param_common(codec);
		wcd9xxx_cfg_clsh_param_hph(codec);
		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
		wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
		wcd9xxx_enable_buck(codec, clsh_d, true);
		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);

		dev_dbg(codec->dev, "%s: Done\n", __func__);
	} else {
		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
		wcd9xxx_enable_buck(codec, clsh_d, false);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, false);
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
	}
}
static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
			struct wcd9xxx_clsh_cdc_data *clsh_d,
			u8 req_state, bool is_enable)
{
	pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
	if (is_enable) {
		wcd9xxx_cfg_clsh_param_common(codec);
		wcd9xxx_cfg_clsh_param_ear(codec);
		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
		wcd9xxx_set_buck_mode(codec, BUCK_VREF_2V);
		wcd9xxx_enable_buck(codec, clsh_d, true);
		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);

		dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
	} else {
		dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
		wcd9xxx_enable_buck(codec, clsh_d, false);
#ifdef CONFIG_MACH_URSA
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, false);
#else
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
#endif
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
	}
}
static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
			struct wcd9xxx_clsh_cdc_data *clsh_d,
			u8 req_state, bool is_enable)
{
	if (is_enable) {
		wcd9xxx_cfg_clsh_param_common(codec);
		wcd9xxx_cfg_clsh_param_ear(codec);
		wcd9xxx_enable_clsh_block(codec, clsh_d, true);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		wcd9xxx_clsh_computation_request(codec,
				CLSH_COMPUTE_EAR, true);
		wcd9xxx_set_buck_mode(codec, BUCK_VREF_2V);
		wcd9xxx_enable_buck(codec, clsh_d, true);
		wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);

		dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
	} else {
		dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
		wcd9xxx_enable_buck(codec, clsh_d, false);
        wcd9xxx_clsh_computation_request(codec,
				CLSH_COMPUTE_EAR, true);
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
	}
}
static void wcd9xxx_clsh_state_ear_lo(struct snd_soc_codec *codec,
			struct wcd9xxx_clsh_cdc_data *clsh_d,
			u8 req_state, bool is_enable)
{

	dev_dbg(codec->dev, "%s: enter %s\n", __func__,
			is_enable ? "enable" : "disable");
	if (is_enable) {
		wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
		wcd9xxx_enable_buck(codec, clsh_d, true);
		if (req_state & WCD9XXX_CLSH_STATE_EAR) {
			wcd9xxx_set_fclk_get_ncp(codec, clsh_d,
						NCP_FCLK_LEVEL_8);
			wcd9xxx_ncp_bypass_enable(codec, true);
			wcd9xxx_enable_clsh_block(codec, clsh_d, true);
			wcd9xxx_chargepump_request(codec, true);
			wcd9xxx_enable_anc_delay(codec, true);
			wcd9xxx_clsh_comp_req(codec, clsh_d,
						CLSH_COMPUTE_EAR, true);
		}
	} else {
		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
		wcd9xxx_ncp_bypass_enable(codec, false);
		if (req_state & WCD9XXX_CLSH_STATE_LO) {
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x20, 0x00);
			wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
		} else if (req_state & WCD9XXX_CLSH_STATE_EAR) {
			wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR,
						false);
			/*sleep 5ms*/
			if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
				wcd9xxx_enable_buck(codec, clsh_d, false);
				wcd9xxx_ncp_bypass_enable(codec, true);
			} else {
				/* NCP settle time recommended by codec	spec */
				usleep_range(NCP_SETTLE_TIME_US,
					     NCP_SETTLE_TIME_US + 10);
				wcd9xxx_clsh_set_Iest(codec, 0x02);
			}
			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
						0x04, 0x00);
			snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_4,
						0xFF, BUCK_VREF_1P8V);
		}
	}
}
static void wcd9xxx_clsh_state_hph_lo(struct snd_soc_codec *codec,
			struct wcd9xxx_clsh_cdc_data *clsh_d,
			u8 req_state, bool is_enable)
{

	dev_dbg(codec->dev, "%s: enter %s\n", __func__,
			is_enable ? "enable" : "disable");
	if (is_enable) {
		if ((clsh_d->state == WCD9XXX_CLSH_STATE_LO) ||
			(req_state == WCD9XXX_CLSH_STATE_LO)) {
			wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
			wcd9xxx_enable_buck(codec, clsh_d, true);
			wcd9xxx_set_fclk_get_ncp(codec, clsh_d,
						NCP_FCLK_LEVEL_8);
			if (req_state & WCD9XXX_CLSH_STATE_HPH_ST) {
				wcd9xxx_ncp_bypass_enable(codec, true);
				wcd9xxx_enable_clsh_block(codec, clsh_d, true);
				wcd9xxx_chargepump_request(codec, true);
				wcd9xxx_enable_anc_delay(codec, true);
			}
		}
		if (req_state == WCD9XXX_CLSH_STATE_HPHL)
			wcd9xxx_clsh_comp_req(codec, clsh_d,
						CLSH_COMPUTE_HPH_L, true);
		if (req_state == WCD9XXX_CLSH_STATE_HPHR)
			wcd9xxx_clsh_comp_req(codec, clsh_d,
						CLSH_COMPUTE_HPH_R, true);
	} else {
		switch (req_state) {
		case WCD9XXX_CLSH_STATE_LO:
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x20, 0x00);
			wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
			break;
		case WCD9XXX_CLSH_STATE_HPHL:
			wcd9xxx_clsh_comp_req(codec, clsh_d,
						CLSH_COMPUTE_HPH_L, false);
			break;
		case WCD9XXX_CLSH_STATE_HPHR:
			wcd9xxx_clsh_comp_req(codec, clsh_d,
						CLSH_COMPUTE_HPH_R, false);
			break;
		default:
			dev_dbg(codec->dev,
				 "%s:Invalid state:0x%x,enable:0x%x\n",
				__func__, req_state, is_enable);
			break;
		}
		if ((req_state == WCD9XXX_CLSH_STATE_LO) ||
		((clsh_d->state & (~req_state)) == WCD9XXX_CLSH_STATE_LO)) {
			wcd9xxx_set_fclk_put_ncp(codec, clsh_d,
						NCP_FCLK_LEVEL_8);
			wcd9xxx_ncp_bypass_enable(codec, false);

			if (req_state & WCD9XXX_CLSH_STATE_HPH_ST) {
				usleep_range(BUCK_SETTLE_TIME_US,
						BUCK_SETTLE_TIME_US + 10);
				if (clsh_d->buck_mv ==
						WCD9XXX_CDC_BUCK_MV_1P8) {
					wcd9xxx_enable_buck(codec, clsh_d,
								false);
					wcd9xxx_ncp_bypass_enable(codec, true);
				} else {
					/*
					 *NCP settle time recommended by codec
					 *specification
					 */
					usleep_range(NCP_SETTLE_TIME_US,
						NCP_SETTLE_TIME_US + 10);
					wcd9xxx_clsh_set_Iest(codec, 0x02);
				}
				snd_soc_update_bits(codec,
						WCD9XXX_A_BUCK_MODE_1,
						0x04, 0x00);
				snd_soc_update_bits(codec,
						 WCD9XXX_A_BUCK_MODE_4,
						0xFF, BUCK_VREF_1P8V);
			}
		}
	}
}