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