diff options
| -rw-r--r-- | sound/soc/codecs/wcd-mbhc-v2.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsd.c | 47 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsd.h | 5 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-mbhc.c | 35 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-mbhc.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x.c | 150 |
6 files changed, 236 insertions, 5 deletions
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 3cbc1e7821cf..a1f23685beb5 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -2593,6 +2593,8 @@ void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier) mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); + mutex_destroy(&mbhc->hphl_pa_lock); + mutex_destroy(&mbhc->hphr_pa_lock); } EXPORT_SYMBOL(wcd_mbhc_deinit); diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsd.c b/sound/soc/codecs/wcd934x/wcd934x-dsd.c index 4e3e769585e6..580591a32ba1 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsd.c +++ b/sound/soc/codecs/wcd934x/wcd934x-dsd.c @@ -619,6 +619,53 @@ static const struct snd_soc_dapm_widget tavil_dsd_widgets[] = { }; /** + * tavil_dsd_post_ssr_init - DSD intialization after subsystem restart + * + * @codec: pointer to snd_soc_codec + * + * Returns 0 on success or error on failure + */ +int tavil_dsd_post_ssr_init(struct tavil_dsd_config *dsd_conf) +{ + struct snd_soc_codec *codec; + + if (!dsd_conf || !dsd_conf->codec) + return -EINVAL; + + codec = dsd_conf->codec; + /* Disable DSD Interrupts */ + snd_soc_update_bits(codec, WCD934X_INTR_CODEC_MISC_MASK, 0x08, 0x08); + + /* DSD registers init */ + if (dsd_conf->version == TAVIL_VERSION_1_0) { + snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2, 0x02, 0x00); + snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2, 0x02, 0x00); + } + /* DSD0: Mute EN */ + snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2, 0x04, 0x04); + /* DSD1: Mute EN */ + snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2, 0x04, 0x04); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG3, 0x10, + 0x10); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG3, 0x10, + 0x10); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG0, 0x0E, + 0x0A); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG0, 0x0E, + 0x0A); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD0_DEBUG_CFG1, 0x07, + 0x04); + snd_soc_update_bits(codec, WCD934X_CDC_DEBUG_DSD1_DEBUG_CFG1, 0x07, + 0x04); + + /* Enable DSD Interrupts */ + snd_soc_update_bits(codec, WCD934X_INTR_CODEC_MISC_MASK, 0x08, 0x00); + + return 0; +} +EXPORT_SYMBOL(tavil_dsd_post_ssr_init); + +/** * tavil_dsd_init - DSD intialization * * @codec: pointer to snd_soc_codec diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsd.h b/sound/soc/codecs/wcd934x/wcd934x-dsd.h index 21450c90a272..498288335b3b 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsd.h +++ b/sound/soc/codecs/wcd934x/wcd934x-dsd.h @@ -55,6 +55,7 @@ void tavil_dsd_set_interp_rate(struct tavil_dsd_config *dsd_conf, u16 rx_port, u32 sample_rate, u8 sample_rate_val); struct tavil_dsd_config *tavil_dsd_init(struct snd_soc_codec *codec); void tavil_dsd_deinit(struct tavil_dsd_config *dsd_config); +int tavil_dsd_post_ssr_init(struct tavil_dsd_config *dsd_config); #else int tavil_dsd_set_mixer_value(struct tavil_dsd_config *dsd_conf, int interp_num, int sw_value) @@ -88,5 +89,9 @@ struct tavil_dsd_config *tavil_dsd_init(struct snd_soc_codec *codec) void tavil_dsd_deinit(struct tavil_dsd_config *dsd_config) { } +int tavil_dsd_post_ssr_init(struct tavil_dsd_config *dsd_config) +{ + return 0; +} #endif #endif diff --git a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c index b3a30eb10b92..d713edbbb355 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c +++ b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c @@ -912,6 +912,37 @@ void tavil_mbhc_hs_detect_exit(struct snd_soc_codec *codec) EXPORT_SYMBOL(tavil_mbhc_hs_detect_exit); /* + * tavil_mbhc_post_ssr_init: initialize mbhc for tavil post subsystem restart + * @mbhc: poniter to wcd934x_mbhc structure + * @codec: handle to snd_soc_codec * + * + * return 0 if mbhc_init is success or error code in case of failure + */ +int tavil_mbhc_post_ssr_init(struct wcd934x_mbhc *mbhc, + struct snd_soc_codec *codec) +{ + int ret; + + if (!mbhc || !codec) + return -EINVAL; + + wcd_mbhc_deinit(&mbhc->wcd_mbhc); + ret = wcd_mbhc_init(&mbhc->wcd_mbhc, codec, &mbhc_cb, &intr_ids, + wcd_mbhc_registers, TAVIL_ZDET_SUPPORTED); + if (ret) { + dev_err(codec->dev, "%s: mbhc initialization failed\n", + __func__); + goto done; + } + snd_soc_update_bits(codec, WCD934X_MBHC_NEW_CTL_1, 0x04, 0x04); + snd_soc_update_bits(codec, WCD934X_MBHC_CTL_BCS, 0x01, 0x01); + +done: + return ret; +} +EXPORT_SYMBOL(tavil_mbhc_post_ssr_init); + +/* * tavil_mbhc_init: initialize mbhc for tavil * @mbhc: poniter to wcd934x_mbhc struct pointer to store the configs * @codec: handle to snd_soc_codec * @@ -977,7 +1008,9 @@ void tavil_mbhc_deinit(struct snd_soc_codec *codec) { struct wcd934x_mbhc *wcd934x_mbhc = tavil_soc_get_mbhc(codec); - if (!wcd934x_mbhc) + if (wcd934x_mbhc) { + wcd_mbhc_deinit(&wcd934x_mbhc->wcd_mbhc); devm_kfree(codec->dev, wcd934x_mbhc); + } } EXPORT_SYMBOL(tavil_mbhc_deinit); diff --git a/sound/soc/codecs/wcd934x/wcd934x-mbhc.h b/sound/soc/codecs/wcd934x/wcd934x-mbhc.h index 120a7b0f8177..3c88a12194af 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-mbhc.h +++ b/sound/soc/codecs/wcd934x/wcd934x-mbhc.h @@ -42,6 +42,8 @@ extern void tavil_mbhc_hs_detect_exit(struct snd_soc_codec *codec); extern int tavil_mbhc_hs_detect(struct snd_soc_codec *codec, struct wcd_mbhc_config *mbhc_cfg); extern void tavil_mbhc_deinit(struct snd_soc_codec *codec); +extern int tavil_mbhc_post_ssr_init(struct wcd934x_mbhc *mbhc, + struct snd_soc_codec *codec); #endif /* __WCD934X_MBHC_H__ */ diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index a526e1afdd28..dc557da07186 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -652,6 +652,8 @@ static const struct tavil_reg_mask_val tavil_spkr_mode1[] = { {WCD934X_CDC_BOOST1_BOOST_CTL, 0x7C, 0x44}, }; +static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil); + /* * wcd934x_get_codec_info: Get codec specific information * @@ -4150,7 +4152,8 @@ int tavil_micbias_control(struct snd_soc_codec *codec, snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80); break; case MICB_PULLUP_DISABLE: - tavil->pullup_ref[micb_index]--; + if (tavil->pullup_ref[micb_index] > 0) + tavil->pullup_ref[micb_index]--; if ((tavil->pullup_ref[micb_index] == 0) && (tavil->micb_ref[micb_index] == 0)) snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00); @@ -4170,7 +4173,8 @@ int tavil_micbias_control(struct snd_soc_codec *codec, post_dapm_on, &tavil->mbhc->wcd_mbhc); break; case MICB_DISABLE: - tavil->micb_ref[micb_index]--; + if (tavil->pullup_ref[micb_index] > 0) + tavil->micb_ref[micb_index]--; if ((tavil->micb_ref[micb_index] == 0) && (tavil->pullup_ref[micb_index] > 0)) snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80); @@ -8282,6 +8286,7 @@ static void tavil_cleanup_irqs(struct tavil_priv *tavil) &wcd9xxx->core_res; wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tavil); + wcd9xxx_free_irq(core_res, WCD934X_IRQ_MISC, tavil); } /* @@ -8533,6 +8538,129 @@ static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil) } } +static int tavil_device_down(struct wcd9xxx *wcd9xxx) +{ + struct snd_soc_codec *codec; + struct tavil_priv *priv; + int count; + + codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv); + priv = snd_soc_codec_get_drvdata(codec); + swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev, + SWR_DEVICE_DOWN, NULL); + tavil_dsd_reset(priv->dsd_config); + snd_soc_card_change_online_state(codec->component.card, 0); + for (count = 0; count < NUM_CODEC_DAIS; count++) + priv->dai[count].bus_down_in_recovery = true; + priv->resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; + + return 0; +} + +static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx) +{ + int i, ret = 0; + struct wcd9xxx *control; + struct snd_soc_codec *codec; + struct tavil_priv *tavil; + struct wcd9xxx_pdata *pdata; + struct wcd_mbhc *mbhc; + + codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv); + tavil = snd_soc_codec_get_drvdata(codec); + control = dev_get_drvdata(codec->dev->parent); + + wcd9xxx_set_power_state(tavil->wcd9xxx, + WCD_REGION_POWER_COLLAPSE_REMOVE, + WCD9XXX_DIG_CORE_REGION_1); + + mutex_lock(&tavil->codec_mutex); + /* + * Codec hardware by default comes up in SVS mode. + * Initialize the svs_ref_cnt to 1 to reflect the hardware + * state in the driver. + */ + tavil->svs_ref_cnt = 1; + + tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la = + control->slim_slave->laddr; + tavil_slimbus_slave_port_cfg.slave_dev_pgd_la = + control->slim->laddr; + tavil_init_slim_slave_cfg(codec); + snd_soc_card_change_online_state(codec->component.card, 1); + + /* Class-H Init */ + wcd_clsh_init(&tavil->clsh_d); + /* Default HPH Mode to Class-H LOHiFi */ + tavil->hph_mode = CLS_H_LOHIFI; + + for (i = 0; i < TAVIL_MAX_MICBIAS; i++) + tavil->micb_ref[i] = 0; + + for (i = 0; i < COMPANDER_MAX; i++) + tavil->comp_enabled[i] = 0; + + dev_dbg(codec->dev, "%s: MCLK Rate = %x\n", + __func__, control->mclk_rate); + + if (control->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ) + snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG, + 0x03, 0x00); + else if (control->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ) + snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG, + 0x03, 0x01); + wcd_resmgr_post_ssr_v2(tavil->resmgr); + tavil_update_reg_defaults(tavil); + tavil_codec_init_reg(tavil); + __tavil_enable_efuse_sensing(tavil); + tavil_mclk2_reg_defaults(tavil); + + __tavil_cdc_mclk_enable(tavil, true); + regcache_mark_dirty(codec->component.regmap); + regcache_sync(codec->component.regmap); + __tavil_cdc_mclk_enable(tavil, false); + + pdata = dev_get_platdata(codec->dev->parent); + ret = tavil_handle_pdata(tavil, pdata); + if (IS_ERR_VALUE(ret)) + dev_err(codec->dev, "%s: invalid pdata\n", __func__); + + /* Initialize MBHC module */ + mbhc = &tavil->mbhc->wcd_mbhc; + ret = tavil_mbhc_post_ssr_init(tavil->mbhc, codec); + if (ret) { + dev_err(codec->dev, "%s: mbhc initialization failed\n", + __func__); + goto done; + } else { + tavil_mbhc_hs_detect(codec, mbhc->mbhc_cfg); + } + + /* DSD initialization */ + ret = tavil_dsd_post_ssr_init(tavil->dsd_config); + if (ret) + dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__); + + tavil_cleanup_irqs(tavil); + ret = tavil_setup_irqs(tavil); + if (ret) { + dev_err(codec->dev, "%s: tavil irq setup failed %d\n", + __func__, ret); + goto done; + } + + tavil_set_spkr_mode(codec, tavil->swr.spkr_mode); + /* + * Once the codec initialization is completed, the svs vote + * can be released allowing the codec to go to SVS2. + */ + tavil_vote_svs(tavil, false); + +done: + mutex_unlock(&tavil->codec_mutex); + return ret; +} + static int tavil_soc_codec_probe(struct snd_soc_codec *codec) { struct wcd9xxx *control; @@ -8548,8 +8676,12 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) tavil = snd_soc_codec_get_drvdata(codec); tavil->intf_type = wcd9xxx_get_intf_type(); + control->dev_down = tavil_device_down; + control->post_reset = tavil_post_reset_cb; + control->ssr_priv = (void *)codec; + /* Resource Manager post Init */ - ret = wcd_resmgr_post_init(tavil->resmgr, NULL, codec); + ret = wcd_resmgr_post_init(tavil->resmgr, &tavil_resmgr_cb, codec); if (ret) { dev_err(codec->dev, "%s: wcd resmgr post init failed\n", __func__); @@ -9160,6 +9292,7 @@ err_mem: static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil) { int val, rc; + struct snd_soc_codec *codec; __tavil_cdc_mclk_enable(tavil, true); @@ -9176,8 +9309,17 @@ static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil) rc = regmap_read(tavil->wcd9xxx->regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val); if (rc || (!(val & 0x01))) - WARN(1, "%s: Efuse sense is not complete\n", __func__); + WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n", + __func__, val, rc); + codec = tavil->codec; + if (!codec) { + pr_debug("%s: codec is not yet registered\n", __func__); + goto done; + } + tavil_enable_sido_buck(codec); + +done: __tavil_cdc_mclk_enable(tavil, false); return rc; |
