コード例 #1
0
static int wm2000_enter_standby(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);

	BUG_ON(wm2000->anc_mode != ANC_ACTIVE);

	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_THERMAL_ENABLE |
			     WM2000_MODE_STANDBY_ENTRY);
	} else {
		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)) {
		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)) {
		dev_err(&i2c->dev,
			"Timed out waiting for standby\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");

	return 0;
}
コード例 #2
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;
}
コード例 #3
0
static int wm2000_power_down(struct i2c_client *i2c, int analogue)
{
	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
	int timeout;

	dev_dbg(&i2c->dev, "Power Down\n");
	if (analogue) {
		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_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");
        goto anc_off_timeout;
//		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;
	}

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

	wm2000_clk_disable();

	return 0;
}
コード例 #4
0
ファイル: wm2000.c プロジェクト: superna9999/linux
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 = ANC_BYPASS;
    dev_dbg(&i2c->dev, "bypass enabled\n");

    return 0;
}
コード例 #5
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;
}
コード例 #6
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;
}
コード例 #7
0
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;
}
コード例 #8
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;
}