static int wm8961_resume(struct snd_soc_codec *codec) { snd_soc_cache_sync(codec); wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; }
static void wm8961_unregister(struct wm8961_priv *wm8961) { wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); snd_soc_unregister_dai(&wm8961_dai); snd_soc_unregister_codec(&wm8961->codec); kfree(wm8961); wm8961_codec = NULL; }
static int wm8961_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; }
static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); /* Latch volume update bits (right channel only, we always * write both out) and default ZC on. */ reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); snd_soc_write(codec, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); snd_soc_write(codec, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); /* Use soft mute by default */ reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); /* Use automatic clocking mode by default; for now this is all * we support. */ reg = snd_soc_read(codec, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_write(codec, WM8961_CLOCKING_3, reg); wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_add_codec_controls(codec, wm8961_snd_controls, ARRAY_SIZE(wm8961_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets, ARRAY_SIZE(wm8961_dapm_widgets)); snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); return 0; }
static int wm8961_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; u16 *reg_cache = codec->reg_cache; int i; for (i = 0; i < codec->reg_cache_size; i++) { if (reg_cache[i] == wm8961_reg_defaults[i]) continue; if (i == WM8961_SOFTWARE_RESET) continue; snd_soc_write(codec, i, reg_cache[i]); } wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; }
static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); if (reg != 0x1801) { dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); return -EINVAL; } codec->cache_bypass = 1; reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); codec->cache_bypass = 0; dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) + 'A'); ret = wm8961_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); return ret; } reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); snd_soc_write(codec, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); snd_soc_write(codec, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); reg = snd_soc_read(codec, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_write(codec, WM8961_CLOCKING_3, reg); wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_add_codec_controls(codec, wm8961_snd_controls, ARRAY_SIZE(wm8961_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets, ARRAY_SIZE(wm8961_dapm_widgets)); snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); return 0; }
static int wm8961_suspend(struct snd_soc_codec *codec) { wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; }
static int wm8961_register(struct wm8961_priv *wm8961) { struct snd_soc_codec *codec = &wm8961->codec; int ret; u16 reg; if (wm8961_codec) { dev_err(codec->dev, "Another WM8961 is registered\n"); ret = -EINVAL; goto err; } mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); snd_soc_codec_set_drvdata(codec, wm8961); codec->name = "WM8961"; codec->owner = THIS_MODULE; codec->dai = &wm8961_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); codec->reg_cache = &wm8961->reg_cache; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8961_set_bias_level; codec->volatile_register = wm8961_volatile_register; memcpy(codec->reg_cache, wm8961_reg_defaults, sizeof(wm8961_reg_defaults)); ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); goto err; } reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); if (reg != 0x1801) { dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); ret = -EINVAL; goto err; } /* This isn't volatile - readback doesn't correspond to write */ reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME); dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) + 'A'); ret = wm8961_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); return ret; } /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); /* Latch volume update bits (right channel only, we always * write both out) and default ZC on. */ reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); snd_soc_write(codec, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); snd_soc_write(codec, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); /* Use soft mute by default */ reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); /* Use automatic clocking mode by default; for now this is all * we support. */ reg = snd_soc_read(codec, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_write(codec, WM8961_CLOCKING_3, reg); wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8961_dai.dev = codec->dev; wm8961_codec = codec; ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); return ret; } ret = snd_soc_register_dai(&wm8961_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); return ret; } return 0; err: kfree(wm8961); return ret; }
static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret = 0; u16 reg; ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); if (reg != 0x1801) { dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); return -EINVAL; } /* This isn't volatile - readback doesn't correspond to write */ codec->cache_bypass = 1; reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); codec->cache_bypass = 0; dev_info(codec->dev, "WM8961 family %d revision %c\n", (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) + 'A'); ret = wm8961_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); return ret; } /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); /* Latch volume update bits (right channel only, we always * write both out) and default ZC on. */ reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); snd_soc_write(codec, WM8961_ROUT1_VOLUME, reg | WM8961_LO1ZC | WM8961_OUT1VU); snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); snd_soc_write(codec, WM8961_ROUT2_VOLUME, reg | WM8961_SPKRZC | WM8961_SPKVU); snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); /* Use soft mute by default */ reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); reg |= WM8961_DACSMM; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); /* Use automatic clocking mode by default; for now this is all * we support. */ reg = snd_soc_read(codec, WM8961_CLOCKING_3); reg &= ~WM8961_MANUAL_MODE; snd_soc_write(codec, WM8961_CLOCKING_3, reg); wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_add_codec_controls(codec, wm8961_snd_controls, ARRAY_SIZE(wm8961_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets, ARRAY_SIZE(wm8961_dapm_widgets)); snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); return 0; }