diff options
| -rw-r--r-- | drivers/mfd/wcd934x-regmap.c | 43 | ||||
| -rw-r--r-- | drivers/mfd/wcd9xxx-regmap.h | 7 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 19 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 78 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 9 | ||||
| -rw-r--r-- | drivers/soc/qcom/msm_smem.c | 6 | ||||
| -rw-r--r-- | include/linux/mfd/wcd934x/registers.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd9335.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsd.c | 33 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-dsd.h | 1 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x.c | 108 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd9xxx-common-v2.c | 5 |
12 files changed, 239 insertions, 76 deletions
diff --git a/drivers/mfd/wcd934x-regmap.c b/drivers/mfd/wcd934x-regmap.c index 02ddf3225af8..e07350a1e2ce 100644 --- a/drivers/mfd/wcd934x-regmap.c +++ b/drivers/mfd/wcd934x-regmap.c @@ -17,6 +17,18 @@ #include <linux/device.h> #include "wcd9xxx-regmap.h" + +static const struct reg_sequence wcd934x_1_1_defaults[] = { + { WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0, 0x01 }, + { WCD934X_BIAS_VBG_FINE_ADJ, 0x75 }, + { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E }, + { WCD934X_EAR_DAC_CTL_ATEST, 0x08 }, + { WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x17 }, + { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 }, + { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x81 }, + { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x81 }, +}; + static const struct reg_default wcd934x_defaults[] = { { WCD934X_PAGE0_PAGE_REGISTER, 0x00 }, { WCD934X_CODEC_RPM_CLK_BYPASS, 0x00 }, @@ -1803,6 +1815,37 @@ static const struct reg_default wcd934x_defaults[] = { { WCD934X_TEST_DEBUG_CODEC_DIAGS, 0x00 }, }; +/* + * wcd934x_regmap_register_patch: Update register defaults based on version + * @regmap: handle to wcd9xxx regmap + * @version: wcd934x version + * + * Returns error code in case of failure or 0 for success + */ +int wcd934x_regmap_register_patch(struct regmap *regmap, int revision) +{ + int rc = 0; + + if (!regmap) { + pr_err("%s: regmap struct is NULL\n", __func__); + return -EINVAL; + } + + switch (revision) { + case TAVIL_VERSION_1_1: + case TAVIL_VERSION_WCD9340_1_1: + case TAVIL_VERSION_WCD9341_1_1: + regcache_cache_only(regmap, true); + rc = regmap_multi_reg_write(regmap, wcd934x_1_1_defaults, + ARRAY_SIZE(wcd934x_1_1_defaults)); + regcache_cache_only(regmap, false); + break; + } + + return rc; +} +EXPORT_SYMBOL(wcd934x_regmap_register_patch); + static bool wcd934x_is_readable_register(struct device *dev, unsigned int reg) { u8 pg_num, reg_offset; diff --git a/drivers/mfd/wcd9xxx-regmap.h b/drivers/mfd/wcd9xxx-regmap.h index 62e4a620c71c..6db8fc55acae 100644 --- a/drivers/mfd/wcd9xxx-regmap.h +++ b/drivers/mfd/wcd9xxx-regmap.h @@ -21,6 +21,8 @@ typedef int (*regmap_patch_fptr)(struct regmap *, int); #ifdef CONFIG_WCD934X_CODEC extern struct regmap_config wcd934x_regmap_config; +extern int wcd934x_regmap_register_patch(struct regmap *regmap, + int version); #endif #ifdef CONFIG_WCD9335_CODEC @@ -71,6 +73,11 @@ static inline regmap_patch_fptr wcd9xxx_get_regmap_reg_patch(int type) apply_patch = wcd9335_regmap_register_patch; break; #endif +#ifdef CONFIG_WCD934X_CODEC + case WCD934X: + apply_patch = wcd934x_regmap_register_patch; + break; +#endif default: apply_patch = NULL; break; diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index ad4b6ffef36e..1a1dd804ffb3 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1498,10 +1498,14 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, /* M-PHY RMMI interface clocks can be turned off */ ufs_qcom_phy_disable_iface_clk(host->generic_phy); - if (!ufs_qcom_is_link_active(hba)) { - if (!is_gating_context) - /* turn off UFS local PHY ref_clk */ - ufs_qcom_phy_disable_ref_clk(host->generic_phy); + /* + * If auto hibern8 is supported then the link will already + * be in hibern8 state and the ref clock can be gated. + */ + if (ufshcd_is_auto_hibern8_supported(hba) || + !ufs_qcom_is_link_active(hba)) { + /* turn off UFS local PHY ref_clk */ + ufs_qcom_phy_disable_ref_clk(host->generic_phy); /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); } @@ -1956,13 +1960,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) host->hba = hba; ufshcd_set_variant(hba, host); - /* - * voting/devoting device ref_clk source is time consuming hence - * skip devoting it during aggressive clock gating. This clock - * will still be gated off during runtime suspend. - */ - hba->no_ref_clk_gating = true; - err = ufs_qcom_ice_get_dev(host); if (err == -EPROBE_DEFER) { /* diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d478767ad3dd..53fed74eaefc 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1176,6 +1176,12 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up) return ret; } +static inline void ufshcd_cancel_gate_work(struct ufs_hba *hba) +{ + hrtimer_cancel(&hba->clk_gating.gate_hrtimer); + cancel_work_sync(&hba->clk_gating.gate_work); +} + static void ufshcd_ungate_work(struct work_struct *work) { int ret; @@ -1183,7 +1189,7 @@ static void ufshcd_ungate_work(struct work_struct *work) struct ufs_hba *hba = container_of(work, struct ufs_hba, clk_gating.ungate_work); - cancel_delayed_work_sync(&hba->clk_gating.gate_work); + ufshcd_cancel_gate_work(hba); spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == CLKS_ON) { @@ -1254,14 +1260,18 @@ start: } break; case REQ_CLKS_OFF: - if (cancel_delayed_work(&hba->clk_gating.gate_work)) { + /* + * If the timer was active but the callback was not running + * we have nothing to do, just change state and return. + */ + if (hrtimer_try_to_cancel(&hba->clk_gating.gate_hrtimer) == 1) { hba->clk_gating.state = CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); break; } /* - * If we here, it means gating work is either done or + * If we are here, it means gating work is either done or * currently running. Hence, fall through to cancel gating * work and to enable clocks. */ @@ -1301,7 +1311,7 @@ EXPORT_SYMBOL_GPL(ufshcd_hold); static void ufshcd_gate_work(struct work_struct *work) { struct ufs_hba *hba = container_of(work, struct ufs_hba, - clk_gating.gate_work.work); + clk_gating.gate_work); unsigned long flags; spin_lock_irqsave(hba->host->host_lock, flags); @@ -1346,7 +1356,12 @@ static void ufshcd_gate_work(struct work_struct *work) ufshcd_set_link_hibern8(hba); } - if (!ufshcd_is_link_active(hba) && !hba->no_ref_clk_gating) + /* + * If auto hibern8 is supported then the link will already + * be in hibern8 state and the ref clock can be gated. + */ + if ((ufshcd_is_auto_hibern8_supported(hba) || + !ufshcd_is_link_active(hba)) && !hba->no_ref_clk_gating) ufshcd_disable_clocks(hba, true); else /* If link is active, device ref_clk can't be switched off */ @@ -1394,8 +1409,9 @@ static void __ufshcd_release(struct ufs_hba *hba, bool no_sched) hba->clk_gating.state = REQ_CLKS_OFF; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - schedule_delayed_work(&hba->clk_gating.gate_work, - msecs_to_jiffies(hba->clk_gating.delay_ms)); + hrtimer_start(&hba->clk_gating.gate_hrtimer, + ms_to_ktime(hba->clk_gating.delay_ms), + HRTIMER_MODE_REL); } void ufshcd_release(struct ufs_hba *hba, bool no_sched) @@ -1523,6 +1539,17 @@ out: return count; } +static enum hrtimer_restart ufshcd_clkgate_hrtimer_handler( + struct hrtimer *timer) +{ + struct ufs_hba *hba = container_of(timer, struct ufs_hba, + clk_gating.gate_hrtimer); + + schedule_work(&hba->clk_gating.gate_work); + + return HRTIMER_NORESTART; +} + static void ufshcd_init_clk_gating(struct ufs_hba *hba) { struct ufs_clk_gating *gating = &hba->clk_gating; @@ -1539,27 +1566,25 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) if (ufshcd_is_auto_hibern8_supported(hba)) hba->caps &= ~UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; - INIT_DELAYED_WORK(&gating->gate_work, ufshcd_gate_work); + INIT_WORK(&gating->gate_work, ufshcd_gate_work); INIT_WORK(&gating->ungate_work, ufshcd_ungate_work); + /* + * Clock gating work must be executed only after auto hibern8 + * timeout has expired in the hardware or after aggressive + * hibern8 on idle software timeout. Using jiffy based low + * resolution delayed work is not reliable to guarantee this, + * hence use a high resolution timer to make sure we schedule + * the gate work precisely more than hibern8 timeout. + * + * Always make sure gating->delay_ms > hibern8_on_idle->delay_ms + */ + hrtimer_init(&gating->gate_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + gating->gate_hrtimer.function = ufshcd_clkgate_hrtimer_handler; gating->is_enabled = true; - /* - * Scheduling the delayed work after 1 jiffies will make the work to - * get schedule any time from 0ms to 1000/HZ ms which is not desirable - * for hibern8 enter work as it may impact the performance if it gets - * scheduled almost immediately. Hence make sure that hibern8 enter - * work gets scheduled atleast after 2 jiffies (any time between - * 1000/HZ ms to 2000/HZ ms). - */ - gating->delay_ms_pwr_save = jiffies_to_msecs( - max_t(unsigned long, - msecs_to_jiffies(UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE), - 2)); - gating->delay_ms_perf = jiffies_to_msecs( - max_t(unsigned long, - msecs_to_jiffies(UFSHCD_CLK_GATING_DELAY_MS_PERF), - 2)); + gating->delay_ms_pwr_save = UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE; + gating->delay_ms_perf = UFSHCD_CLK_GATING_DELAY_MS_PERF; /* start with performance mode */ gating->delay_ms = gating->delay_ms_perf; @@ -1616,8 +1641,8 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) device_remove_file(hba->dev, &hba->clk_gating.delay_attr); } device_remove_file(hba->dev, &hba->clk_gating.enable_attr); + ufshcd_cancel_gate_work(hba); cancel_work_sync(&hba->clk_gating.ungate_work); - cancel_delayed_work_sync(&hba->clk_gating.gate_work); } static void ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba, u32 delay) @@ -1928,6 +1953,7 @@ static void ufshcd_init_hibern8_on_idle(struct ufs_hba *hba) return; if (ufshcd_is_auto_hibern8_supported(hba)) { + hba->hibern8_on_idle.delay_ms = 1; hba->hibern8_on_idle.state = AUTO_HIBERN8; /* * Disable SW hibern8 enter on idle in case @@ -1935,13 +1961,13 @@ static void ufshcd_init_hibern8_on_idle(struct ufs_hba *hba) */ hba->caps &= ~UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE; } else { + hba->hibern8_on_idle.delay_ms = 10; INIT_DELAYED_WORK(&hba->hibern8_on_idle.enter_work, ufshcd_hibern8_enter_work); INIT_WORK(&hba->hibern8_on_idle.exit_work, ufshcd_hibern8_exit_work); } - hba->hibern8_on_idle.delay_ms = 10; hba->hibern8_on_idle.is_enabled = true; hba->hibern8_on_idle.delay_attr.show = diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index a6298f614a0b..cd15d67cf8d5 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -39,6 +39,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/hrtimer.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -396,8 +397,9 @@ enum clk_gating_state { /** * struct ufs_clk_gating - UFS clock gating related info - * @gate_work: worker to turn off clocks after some delay as specified in - * delay_ms + * @gate_hrtimer: hrtimer to invoke @gate_work after some delay as + * specified in @delay_ms + * @gate_work: worker to turn off clocks * @ungate_work: worker to turn on clocks that will be used in case of * interrupt context * @state: the current clocks state @@ -415,7 +417,8 @@ enum clk_gating_state { * completion before gating clocks. */ struct ufs_clk_gating { - struct delayed_work gate_work; + struct hrtimer gate_hrtimer; + struct work_struct gate_work; struct work_struct ungate_work; enum clk_gating_state state; unsigned long delay_ms; diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c index 881359d444fc..cd3d387645fd 100644 --- a/drivers/soc/qcom/msm_smem.c +++ b/drivers/soc/qcom/msm_smem.c @@ -79,6 +79,7 @@ static int spinlocks_initialized; static void *smem_ramdump_dev; static DEFINE_MUTEX(spinlock_init_lock); static DEFINE_SPINLOCK(smem_init_check_lock); +static struct device *smem_dev; static int smem_module_inited; static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list); static DEFINE_MUTEX(smem_module_init_notifier_lock); @@ -1047,7 +1048,8 @@ static __init int modem_restart_late_init(void) void *handle; struct restart_notifier_block *nb; - smem_ramdump_dev = create_ramdump_device("smem", NULL); + if (smem_dev) + smem_ramdump_dev = create_ramdump_device("smem", smem_dev); if (IS_ERR_OR_NULL(smem_ramdump_dev)) { LOG_ERR("%s: Unable to create smem ramdump device.\n", __func__); @@ -1444,7 +1446,7 @@ smem_targ_info_done: SMEM_INFO("smem security enabled\n"); smem_init_security(); } - + smem_dev = &pdev->dev; probe_done = true; ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); diff --git a/include/linux/mfd/wcd934x/registers.h b/include/linux/mfd/wcd934x/registers.h index 085e16d66bc4..a824875096e4 100644 --- a/include/linux/mfd/wcd934x/registers.h +++ b/include/linux/mfd/wcd934x/registers.h @@ -800,9 +800,11 @@ enum { #define WCD934X_VBADC_NEW_ADC_DOUTLSB 0x0731 #define WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL 0x0732 #define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL 0x0733 +#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733 #define WCD934X_HPH_NEW_INT_RDAC_VREF_CTL 0x0734 #define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735 #define WCD934X_HPH_NEW_INT_RDAC_MISC1 0x0736 +#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R 0x0736 #define WCD934X_HPH_NEW_INT_PA_MISC1 0x0737 #define WCD934X_HPH_NEW_INT_PA_MISC2 0x0738 #define WCD934X_HPH_NEW_INT_PA_RDAC_MISC 0x0739 diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 46b8e7f72eb8..9394ee52cad0 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -4596,9 +4596,11 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, if (!ret) { wcd_clsh_imped_config(codec, impedl, false); set_bit(CLASSH_CONFIG, &tasha->status_mask); - } else + } else { dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n", __func__, ret); + ret = 0; + } break; diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsd.c b/sound/soc/codecs/wcd934x/wcd934x-dsd.c index 55072466af55..4e3e769585e6 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsd.c +++ b/sound/soc/codecs/wcd934x/wcd934x-dsd.c @@ -28,6 +28,9 @@ #define DSD_VOLUME_STEP_DELAY_US ((1000 * DSD_VOLUME_UPDATE_DELAY_MS) / \ (2 * DSD_VOLUME_STEPS)) +#define TAVIL_VERSION_1_0 0 +#define TAVIL_VERSION_1_1 1 + static const DECLARE_TLV_DB_MINMAX(tavil_dsd_db_scale, DSD_VOLUME_MIN_M110dB, DSD_VOLUME_MAX_0dB); @@ -369,6 +372,14 @@ static void tavil_dsd_data_pull(struct snd_soc_codec *codec, int dsd_num, } } +static void tavil_dsd_update_volume(struct tavil_dsd_config *dsd_conf) +{ + snd_soc_update_bits(dsd_conf->codec, WCD934X_CDC_TOP_TOP_CFG0, + 0x01, 0x01); + snd_soc_update_bits(dsd_conf->codec, WCD934X_CDC_TOP_TOP_CFG0, + 0x01, 0x00); +} + static int tavil_enable_dsd(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -429,6 +440,8 @@ static int tavil_enable_dsd(struct snd_soc_dapm_widget *w, /* Apply Gain */ snd_soc_write(codec, WCD934X_CDC_DSD0_CFG1, dsd_conf->volume[DSD0]); + if (dsd_conf->version == TAVIL_VERSION_1_1) + tavil_dsd_update_volume(dsd_conf); } else if (w->shift == DSD1) { snd_soc_update_bits(codec, WCD934X_CDC_DSD1_PATH_CTL, @@ -440,6 +453,8 @@ static int tavil_enable_dsd(struct snd_soc_dapm_widget *w, /* Apply Gain */ snd_soc_write(codec, WCD934X_CDC_DSD1_CFG1, dsd_conf->volume[DSD1]); + if (dsd_conf->version == TAVIL_VERSION_1_1) + tavil_dsd_update_volume(dsd_conf); } /* 10msec sleep required after DSD clock is set */ usleep_range(10000, 10100); @@ -538,16 +553,23 @@ static int tavil_dsd_vol_put(struct snd_kcontrol *kcontrol, snd_soc_write(codec, WCD934X_CDC_DSD0_CFG1 + 16 * dsd_idx, nv1); + if (dsd_conf->version == TAVIL_VERSION_1_1) + tavil_dsd_update_volume(dsd_conf); + /* sleep required after each volume step */ usleep_range(DSD_VOLUME_STEP_DELAY_US, (DSD_VOLUME_STEP_DELAY_US + DSD_VOLUME_USLEEP_MARGIN_US)); } - if (nv1 != nv[dsd_idx]) + if (nv1 != nv[dsd_idx]) { snd_soc_write(codec, WCD934X_CDC_DSD0_CFG1 + 16 * dsd_idx, nv[dsd_idx]); + if (dsd_conf->version == TAVIL_VERSION_1_1) + tavil_dsd_update_volume(dsd_conf); + } + dsd_conf->volume[dsd_idx] = nv[dsd_idx]; } @@ -629,9 +651,14 @@ struct tavil_dsd_config *tavil_dsd_init(struct snd_soc_codec *codec) dsd_conf->codec = codec; + /* Read version */ + dsd_conf->version = snd_soc_read(codec, + WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0); /* DSD registers init */ - snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2, 0x02, 0x00); - snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2, 0x02, 0x00); + 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 */ diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsd.h b/sound/soc/codecs/wcd934x/wcd934x-dsd.h index c033795beb9b..21450c90a272 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-dsd.h +++ b/sound/soc/codecs/wcd934x/wcd934x-dsd.h @@ -40,6 +40,7 @@ struct tavil_dsd_config { u32 base_sample_rate[DSD_MAX]; int volume[DSD_MAX]; struct mutex vol_mutex; + int version; }; #ifdef CONFIG_SND_SOC_WCD934X_DSD diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 9e18c17d6f1c..c0996e24e3d6 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -1859,8 +1859,9 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, - 0x06, (0x03 << 1)); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, + 0x06, (0x03 << 1)); set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) { @@ -1922,8 +1923,9 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, blocking_notifier_call_chain(&tavil->mbhc->notifier, WCD_EVENT_POST_HPHR_PA_OFF, &tavil->mbhc->wcd_mbhc); - snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, - 0x06, 0x0); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, + 0x06, 0x0); break; }; @@ -1942,8 +1944,9 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, - 0x06, (0x03 << 1)); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, + 0x06, (0x03 << 1)); set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) { @@ -2004,8 +2007,9 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, blocking_notifier_call_chain(&tavil->mbhc->notifier, WCD_EVENT_POST_HPHL_PA_OFF, &tavil->mbhc->wcd_mbhc); - snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, - 0x06, 0x0); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, + 0x06, 0x0); break; }; @@ -2130,9 +2134,10 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00); /* Set RDAC gain */ - snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, - 0xF0, 0x40); - + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, + WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, + 0xF0, 0x40); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) hph_mode = CLS_H_HIFI; @@ -2155,8 +2160,10 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, WCD934X_SIDO_NEW_VOUT_D_FREQ2, 0x01, 0x0); /* Re-set RDAC gain */ - snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, - 0xF0, 0x0); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, + WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, + 0xF0, 0x0); break; default: break; @@ -2199,8 +2206,10 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00); /* Set RDAC gain */ - snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, - 0xF0, 0x40); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, + WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, + 0xF0, 0x40); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) hph_mode = CLS_H_HIFI; @@ -2223,8 +2232,10 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, WCD934X_SIDO_NEW_VOUT_D_FREQ2, 0x01, 0x0); /* Re-set RDAC gain */ - snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, - 0xF0, 0x0); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) + snd_soc_update_bits(codec, + WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, + 0xF0, 0x0); break; default: break; @@ -2820,11 +2831,15 @@ static void tavil_codec_hphdelay_lutbypass(struct snd_soc_codec *codec, } } -static void tavil_codec_hd2_control(struct snd_soc_codec *codec, +static void tavil_codec_hd2_control(struct tavil_priv *priv, u16 interp_idx, int event) { u16 hd2_scale_reg; u16 hd2_enable_reg = 0; + struct snd_soc_codec *codec = priv->codec; + + if (TAVIL_IS_1_1(priv->wcd9xxx)) + return; switch (interp_idx) { case INTERP_HPHL: @@ -3002,7 +3017,7 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec, snd_soc_update_bits(codec, main_reg, 0x20, 0x20); tavil_codec_idle_detect_control(codec, interp_idx, event); - tavil_codec_hd2_control(codec, interp_idx, event); + tavil_codec_hd2_control(tavil, interp_idx, event); tavil_codec_hphdelay_lutbypass(codec, interp_idx, event); tavil_config_compander(codec, interp_idx, event); @@ -3017,7 +3032,7 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec, tavil_config_compander(codec, interp_idx, event); tavil_codec_hphdelay_lutbypass(codec, interp_idx, event); - tavil_codec_hd2_control(codec, interp_idx, event); + tavil_codec_hd2_control(tavil, interp_idx, event); tavil_codec_idle_detect_control(codec, interp_idx, event); /* Clk Disable */ @@ -7837,7 +7852,11 @@ static const struct wcd_resmgr_cb tavil_resmgr_cb = { .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl, }; -static const struct tavil_reg_mask_val tavil_codec_mclk2_defaults[] = { +static const struct tavil_reg_mask_val tavil_codec_mclk2_1_1_defaults[] = { + {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20}, +}; + +static const struct tavil_reg_mask_val tavil_codec_mclk2_1_0_defaults[] = { /* * PLL Settings: * Clock Root: MCLK2, @@ -7896,6 +7915,13 @@ static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = { {WCD934X_HPH_R_TEST, 0x01, 0x01}, }; +static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = { + {WCD934X_CDC_COMPANDER1_CTL7, 0x1E, 0x06}, + {WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06}, + {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84}, + {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84}, +}; + static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = { {WCD934X_CDC_CLSH_K2_MSB, 0x0F, 0x00}, {WCD934X_CDC_CLSH_K2_LSB, 0xFF, 0x60}, @@ -7922,8 +7948,9 @@ static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = { {WCD934X_CPE_SS_SVA_CFG, 0x60, 0x00}, }; -static void tavil_codec_init_reg(struct snd_soc_codec *codec) +static void tavil_codec_init_reg(struct tavil_priv *priv) { + struct snd_soc_codec *codec = priv->codec; u32 i; for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_common_val); i++) @@ -7931,6 +7958,14 @@ static void tavil_codec_init_reg(struct snd_soc_codec *codec) tavil_codec_reg_init_common_val[i].reg, tavil_codec_reg_init_common_val[i].mask, tavil_codec_reg_init_common_val[i].val); + + if (TAVIL_IS_1_1(priv->wcd9xxx)) { + for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_1_1_val); i++) + snd_soc_update_bits(codec, + tavil_codec_reg_init_1_1_val[i].reg, + tavil_codec_reg_init_1_1_val[i].mask, + tavil_codec_reg_init_1_1_val[i].val); + } } static void tavil_update_reg_defaults(struct tavil_priv *tavil) @@ -8367,11 +8402,22 @@ static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil) int i; struct snd_soc_codec *codec = tavil->codec; - /* MCLK2 configuration */ - for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_defaults); i++) - snd_soc_update_bits(codec, tavil_codec_mclk2_defaults[i].reg, - tavil_codec_mclk2_defaults[i].mask, - tavil_codec_mclk2_defaults[i].val); + if (TAVIL_IS_1_0(tavil->wcd9xxx)) { + /* MCLK2 configuration */ + for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_0_defaults); i++) + snd_soc_update_bits(codec, + tavil_codec_mclk2_1_0_defaults[i].reg, + tavil_codec_mclk2_1_0_defaults[i].mask, + tavil_codec_mclk2_1_0_defaults[i].val); + } + if (TAVIL_IS_1_1(tavil->wcd9xxx)) { + /* MCLK2 configuration */ + for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_1_defaults); i++) + snd_soc_update_bits(codec, + tavil_codec_mclk2_1_1_defaults[i].reg, + tavil_codec_mclk2_1_1_defaults[i].mask, + tavil_codec_mclk2_1_1_defaults[i].val); + } } static int tavil_soc_codec_probe(struct snd_soc_codec *codec) @@ -8429,7 +8475,7 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) for (i = 0; i < COMPANDER_MAX; i++) tavil->comp_enabled[i] = 0; - tavil_codec_init_reg(codec); + tavil_codec_init_reg(tavil); tavil_enable_sido_buck(codec); pdata = dev_get_platdata(codec->dev->parent); @@ -8749,6 +8795,9 @@ static int tavil_swrm_clock(void *handle, bool enable) if (enable) { tavil->swr.clk_users++; if (tavil->swr.clk_users == 1) { + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_TEST_DEBUG_NPL_DLY_TEST_1, + 0x10, 0x00); __tavil_cdc_mclk_enable(tavil, true); regmap_update_bits(tavil->wcd9xxx->regmap, WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL, @@ -8761,6 +8810,9 @@ static int tavil_swrm_clock(void *handle, bool enable) WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL, 0x01, 0x00); __tavil_cdc_mclk_enable(tavil, false); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_TEST_DEBUG_NPL_DLY_TEST_1, + 0x10, 0x10); } } dev_dbg(tavil->dev, "%s: swrm clock users %d\n", diff --git a/sound/soc/codecs/wcd9xxx-common-v2.c b/sound/soc/codecs/wcd9xxx-common-v2.c index 63872bbf540c..47518ec92661 100644 --- a/sound/soc/codecs/wcd9xxx-common-v2.c +++ b/sound/soc/codecs/wcd9xxx-common-v2.c @@ -369,8 +369,9 @@ static inline void wcd_clsh_gm3_boost_disable(struct snd_soc_codec *codec, if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI || mode == CLS_AB_HIFI || mode == CLS_AB) { - snd_soc_update_bits(codec, WCD9XXX_HPH_CNP_WG_CTL, - 0x80, 0x0); /* disable GM3 Boost */ + if (TAVIL_IS_1_0(wcd9xxx)) + snd_soc_update_bits(codec, WCD9XXX_HPH_CNP_WG_CTL, + 0x80, 0x0); /* disable GM3 Boost */ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEG_CTRL_4, 0xF0, 0x80); } else { |
