static int wm2000_power_down(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4);
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_POWER_DOWN);
	} else {
		timeout = 10;
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_POWER_DOWN);
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC power down\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
			     WM2000_ANC_ENG_IDLE, 1)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n");
		return -ETIMEDOUT;
	}

	dev_dbg(&i2c->dev, "powered off\n");
	wm2000->anc_mode = ANC_OFF;

	return 0;
}
Example #2
0
static int wm2000_power_down(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	if (analogue) {
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4);
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_POWER_DOWN);
	} else {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_POWER_DOWN);
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_POWER_DOWN_COMPLETE)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC power down\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
			     WM2000_ANC_ENG_IDLE)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n");
		return -ETIMEDOUT;
	}

	regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);

	dev_dbg(&i2c->dev, "powered off\n");
	wm2000->anc_mode = ANC_OFF;

	return 0;
}
static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	BUG_ON(wm2000->anc_mode != ANC_BYPASS);
	
	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);

	if (analogue) {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	} else {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_MOUSE_ACTIVE, 10)) {
		dev_err(&i2c->dev, "Timed out waiting for MOUSE\n");
		return -ETIMEDOUT;
	}

	wm2000->anc_mode = ANC_ACTIVE;
	dev_dbg(&i2c->dev, "MOUSE active\n");

	return 0;
}
Example #4
0
static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	if (WARN_ON(wm2000->anc_mode != ANC_ACTIVE))
		return -EINVAL;

	if (analogue) {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	} else {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_ANC_DISABLED)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC disable\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
			     WM2000_ANC_ENG_IDLE)) {
		dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n");
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);

	wm2000->anc_mode 
static void wm2000_reset(struct wm2000_priv *wm2000)
{
	struct i2c_client *i2c = wm2000->i2c;

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);
	wm2000_write(i2c, WM2000_REG_ID1, 0);

	wm2000->anc_mode = ANC_OFF;
}
static int wm2000_enter_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout = 4000;

	dev_dbg(&i2c->dev, "enter standby\n");
	WARN_ON(wm2000->anc_mode != ANC_ACTIVE);

	/* Make sure power up completed */
	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_MOUSE_ACTIVE, timeout)) {
		dev_err(&i2c->dev, "Timed out waiting for device after %dms\n",
			timeout * 10);
		return -ETIMEDOUT;
	}

	if (analogue) {
		dev_dbg(&i2c->dev, "enter standby analog=1\n");
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 1);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	} else {
		dev_dbg(&i2c->dev, "enter standby analog=0\n");
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	}

    if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_STANDBY_COMPLETE, timeout)) {
		dev_err(&i2c->dev,
			"Timed out waiting for ANC disable after 1ms\n");
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);

	wm2000->anc_mode = ANC_STANDBY;
	dev_dbg(&i2c->dev, "standby\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue disabled\n");

	wm2000_clk_disable();

	return 0;
}
static int wm2000_enter_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;

	BUG_ON(wm2000->anc_mode != ANC_ACTIVE);

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	} else {
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_ANC_DISABLED, timeout)) {
		dev_err(&i2c->dev,
			"Timed out waiting for ANC disable after 1ms\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE,
			     1)) {
		dev_err(&i2c->dev,
			"Timed out waiting for standby after %dms\n",
			timeout * 10);
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);

	wm2000->anc_mode = ANC_STANDBY;
	dev_dbg(&i2c->dev, "standby\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue disabled\n");

	return 0;
}
static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
	struct i2c_client *i2c = wm2000->i2c;

	int val = ucontrol->value.enumerated.item[0];

	if (val > 1)
		return -EINVAL;

	wm2000->spk_ena = val;
	val = wm2000_read(i2c, WM2000_REG_SPK_CTL);
	if (wm2000->spk_ena)
		val |= 0x21;
	else
		val &= 0xfe;
	wm2000_write(i2c, WM2000_REG_SPK_CTL, val);
	dev_dbg(&i2c->dev,"wm2000 anc speaker put val 2 = %02x\n", val);

	return 0;

	//return wm2000_anc_set_mode(wm2000);
}
static int wm2000_enter_bypass_from_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	wm2000_clk_enable();
	dev_dbg(&i2c->dev, "enter bypass from standby\n");
	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);

    wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 1);
	if (analogue) {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	} else {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	wm2000->anc_mode = ANC_BYPASS;
	dev_dbg(&i2c->dev, "bypass from standby enabled\n");

	return 0;
}
static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	dev_dbg(&i2c->dev, "enter bypass\n");
	WARN_ON(wm2000->anc_mode != ANC_ACTIVE);

	/* Make sure power up completed */
	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_MOUSE_ACTIVE, 4000)) {
		dev_err(&i2c->dev, "Timed out waiting for device after %dms\n",
			4000 * 10);
		return -ETIMEDOUT;
	}

	if (analogue) {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	} else {
		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_BYPASS_ENTRY);
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
				     WM2000_STATUS_BYPASS_COMPLETE, 100)) {
			dev_err(&i2c->dev, "Timeout waiting for BYPASS complete\n");
			return -ETIMEDOUT;
		}

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);

	wm2000->anc_mode = ANC_BYPASS;
	dev_dbg(&i2c->dev, "bypass enabled\n");

	return 0;
}
static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
	struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
       struct i2c_client *i2c = wm2000->i2c;
	int val;

	dev_dbg(&i2c->dev,"wm2000 anc speaker get\n");
	ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
	val = wm2000_read(i2c, WM2000_REG_SPK_CTL);
	if (wm2000->spk_ena)
		val |= 0x21;
	else
		val &= 0xfe;
	wm2000_write(i2c, WM2000_REG_SPK_CTL, val);
	return 0;
}
static int wm2000_exit_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;
    int value;

	dev_dbg(&i2c->dev, "exit standby\n");
	WARN_ON(wm2000->anc_mode != ANC_STANDBY);

	wm2000_clk_enable();

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 1);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_MOUSE_ENABLE);
	} else {
		timeout = 100;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_MOUSE_ENABLE);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

      /*keep WM2000_REG_SPK_CTL default output off*/
	value = wm2000_read(i2c, WM2000_REG_SPK_CTL);
	value &= 0xfe;
	wm2000_write(i2c, WM2000_REG_SPK_CTL, value);
	value = wm2000_read(i2c, WM2000_REG_SPK_CTL);
	dev_dbg(&i2c->dev,"wm2000 anc speaker get val 1 = %02x\n", value);

	wm2000->anc_mode = ANC_ACTIVE;
	dev_dbg(&i2c->dev, "MOUSE active\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue enabled\n");

	return 0;
}
static int wm2000_exit_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;

	BUG_ON(wm2000->anc_mode != ANC_STANDBY);

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_MOUSE_ENABLE);
	} else {
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_MOUSE_ENABLE);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_MOUSE_ACTIVE, timeout)) {
		dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n",
			timeout * 10);
		return -ETIMEDOUT;
	}

	wm2000->anc_mode = ANC_ACTIVE;
	dev_dbg(&i2c->dev, "MOUSE active\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue enabled\n");

	return 0;
}
static int wm2000_power_up(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int ret, timeout;
       int retry_times = 3;
	int value;

	WARN_ON(wm2000->anc_mode != ANC_OFF);

	dev_dbg(&i2c->dev, "Beginning power up\n");

	wm2000_clk_enable();

	if (!wm2000->mclk_div) {
		dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_CLR);
	} else {
		dev_dbg(&i2c->dev, "Enabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_SET);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET);

	/* Wait for ANC engine to become ready */
	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
			     WM2000_ANC_ENG_IDLE, 1)) {
		dev_err(&i2c->dev, "ANC engine failed to reset\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_BOOT_COMPLETE, 1)) {
		dev_err(&i2c->dev, "ANC engine failed to initialise\n");
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);

retry:
	/* Open code download of the data since it is the only bulk
	 * write we do. */
	dev_dbg(&i2c->dev, "Downloading %d bytes\n",
		wm2000->anc_download_size - 2);

	ret = i2c_master_send(i2c, wm2000->anc_download,
			      wm2000->anc_download_size);
	if (ret < 0) {
		dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret);
        if (retry_times--) {
            goto retry;
        }
		return ret;
	}
	if (ret != wm2000->anc_download_size) {
		dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n",
			ret, wm2000->anc_download_size);
		return -EIO;
	}

	dev_dbg(&i2c->dev, "Download complete\n");

	ret = wm2000_read(i2c, WM2000_REG_ANC_GAIN_CTRL);
	printk("wm2000 anc gain:0x%x\n", ret);
	wm2000_write(i2c, WM2000_REG_ANC_GAIN_CTRL, 42); // Add for ANC gain adjustment, 126: big gain 58:-3dB,
//	wm2000_write(i2c, WM2000_REG_MSE_TH2, 0x08); // 0x08:55dBSPL, 0x90:80dBSPL
//	wm2000_write(i2c, WM2000_REG_MSE_TH1, 0x04); // 0x04:55dBSPL, 0x48:74dBSPL

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 1);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	} else {
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	}

	ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY);
	if (wm2000->speech_clarity) {
	        dev_dbg(&i2c->dev, "Disabling Speech Clarity\n");
		ret &= ~WM2000_SPEECH_CLARITY;
	}
	else {
	        dev_dbg(&i2c->dev, "Enabling Speech Clarity\n");
		ret |= WM2000_SPEECH_CLARITY;
	}
	wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret);

	wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33);
	wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02);

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	dev_dbg(&i2c->dev, "ANC active\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue active\n");

	/*keep WM2000_REG_SPK_CTL default output off*/
	value = wm2000_read(i2c, WM2000_REG_SPK_CTL);
	value &= 0xfe;
	wm2000_write(i2c, WM2000_REG_SPK_CTL, value);

	wm2000->anc_mode = ANC_ACTIVE;

	return 0;
}
static int wm2000_power_up(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int ret, timeout;

	BUG_ON(wm2000->anc_mode != ANC_OFF);

	dev_dbg(&i2c->dev, "Beginning power up\n");

	if (!wm2000->mclk_div) {
		dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_CLR);
	} else {
		dev_dbg(&i2c->dev, "Enabling MCLK divider\n");
		wm2000_write(i2c, WM2000_REG_SYS_CTL2,
			     WM2000_MCLK_DIV2_ENA_SET);
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET);

	/* Wait for ANC engine to become ready */
	if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
			     WM2000_ANC_ENG_IDLE, 1)) {
		dev_err(&i2c->dev, "ANC engine failed to reset\n");
		return -ETIMEDOUT;
	}

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_BOOT_COMPLETE, 1)) {
		dev_err(&i2c->dev, "ANC engine failed to initialise\n");
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);

	/* Open code download of the data since it is the only bulk
	 * write we do. */
	dev_dbg(&i2c->dev, "Downloading %d bytes\n",
		wm2000->anc_download_size - 2);

	ret = i2c_master_send(i2c, wm2000->anc_download,
			      wm2000->anc_download_size);
	if (ret < 0) {
		dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret);
		return ret;
	}
	if (ret != wm2000->anc_download_size) {
		dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n",
			ret, wm2000->anc_download_size);
		return -EIO;
	}

	dev_dbg(&i2c->dev, "Download complete\n");

	if (analogue) {
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	} else {
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_MOUSE_ENABLE |
			     WM2000_MODE_THERMAL_ENABLE);
	}

	ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY);
	if (wm2000->speech_clarity)
		ret |= WM2000_SPEECH_CLARITY;
	else
		ret &= ~WM2000_SPEECH_CLARITY;
	wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret);

	wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33);
	wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02);

	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_MOUSE_ACTIVE, timeout)) {
		dev_err(&i2c->dev, "Timed out waiting for device after %dms\n",
			timeout * 10);
		return -ETIMEDOUT;
	}

	dev_dbg(&i2c->dev, "ANC active\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue active\n");
	wm2000->anc_mode = ANC_ACTIVE;

	return 0;
}
static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
				      const struct i2c_device_id *i2c_id)
{
	struct wm2000_priv *wm2000;
	struct wm2000_platform_data *pdata;
	const char *filename;
	const struct firmware *fw = NULL;
	int ret;
	int reg;
	u16 id;

#ifdef WM2000_GPIO_ENABLE
	wm2000_gpio_request();
#endif

	wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
			      GFP_KERNEL);
	if (wm2000 == NULL) {
		dev_err(&i2c->dev, "Unable to allocate private data\n");
		return -ENOMEM;
	}

	dev_set_drvdata(&i2c->dev, wm2000);
	mutex_init(&wm2000->anc_lock);

	wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap);
	if (IS_ERR(wm2000->regmap)) {
		ret = PTR_ERR(wm2000->regmap);
		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
			ret);
		goto err;
	}

    /* when the system reboot, the power supply of wm2000 is always supplied,
     * so there is the bug solution below, powerdown and powerup the module before
     * probed!
     */
    ret=wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);
    ret=wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 1);
    ret=wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
            WM2000_MODE_ANA_SEQ_INCLUDE |
            WM2000_MODE_THERMAL_ENABLE |
            WM2000_MODE_MOUSE_ENABLE);

	/* Verify that this is a WM2000 */
	reg = wm2000_read(i2c, WM2000_REG_ID1);
	id = reg << 8;
	reg = wm2000_read(i2c, WM2000_REG_ID2);
	id |= reg & 0xff;

	if (id != 0x2000) {
		dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
		wm2000_id = 0;
		ret = -ENODEV;
		goto out_regmap_exit;
	} else 
		wm2000_id = 2000;
	printk("wm2000_id = 0x%x\n", id);

	reg = wm2000_read(i2c, WM2000_REG_REVISON);
	dev_info(&i2c->dev, "revision %c\n", reg + 'A');

	filename = "wm2000_anc.bin";
	pdata = dev_get_platdata(&i2c->dev);
	wm2000->mclk_div = 1;
	wm2000->speech_clarity = 0;
	if (pdata) {
		wm2000->mclk_div = pdata->mclkdiv2;
		wm2000->speech_clarity = !pdata->speech_enh_disable;

		if (pdata->download_file)
			filename = pdata->download_file;
	}

	ret = request_firmware(&fw, filename, &i2c->dev);
	if (ret != 0) {
		dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
		goto out;
	}

	/* Pre-cook the concatenation of the register address onto the image */
	wm2000->anc_download_size = fw->size + 2;
	wm2000->anc_download = devm_kzalloc(&i2c->dev,
					    wm2000->anc_download_size,
					    GFP_KERNEL);
	if (wm2000->anc_download == NULL) {
		dev_err(&i2c->dev, "Out of memory\n");
		ret = -ENOMEM;
		goto out;
	}

	wm2000->anc_download[0] = 0x80;
	wm2000->anc_download[1] = 0x00;
	memcpy(wm2000->anc_download + 2, fw->data, fw->size);

	wm2000->anc_eng_ena = 0;
	wm2000->anc_active = 0;
	wm2000->spk_ena = 1;
	wm2000->incall_mode =0;
	wm2000->i2c = i2c;

	wm2000_reset(wm2000);

	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);

	if (!ret) {
		release_firmware(fw);
		return ret;
	}

out:
	release_firmware(fw);
out_regmap_exit:
	regmap_exit(wm2000->regmap);
err:
	devm_kfree(&i2c->dev, wm2000);
	return ret;
}
static int wm2000_enter_standby_from_bypass(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;

	dev_dbg(&i2c->dev, "enter standby from bypass\n");

	// bring system out of stanby
	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); // clear standby bit
	// enable RAM before writing any thing to ram
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
	wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 1);

    /*Make sure wm2000 bypass complete*/
	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_BYPASS_COMPLETE, 100)) {
		dev_err(&i2c->dev, "Timeout waiting for BYPASS complete\n");
		return -ETIMEDOUT;
	}

	if (analogue) {
		dev_dbg(&i2c->dev, "enter standby analog=1\n");
		timeout = 248;
		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 1);

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_ANA_SEQ_INCLUDE |
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	} else {
		dev_dbg(&i2c->dev, "enter standby analog=0\n");
		timeout = 10;

		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
			     WM2000_MODE_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	}

	// wake up ANC engine
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);

	timeout = 1000;
	if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
			     WM2000_STATUS_STANDBY_COMPLETE, timeout)) {
		dev_err(&i2c->dev,
			"Timed out waiting for WM2000_STATUS_STANDBY_COMPLETE after %dms\n", timeout);
		return -ETIMEDOUT;
	}

	wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
	wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);

	wm2000->anc_mode = ANC_STANDBY;
	dev_dbg(&i2c->dev, "standby from bypass\n");
	if (analogue)
		dev_dbg(&i2c->dev, "Analogue disabled\n");

	wm2000_clk_disable();

	return 0;
}