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; }
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_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; }
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; }
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; 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 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; }
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; }