summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/wcd934x-regmap.c43
-rw-r--r--drivers/mfd/wcd9xxx-regmap.h7
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c19
-rw-r--r--drivers/scsi/ufs/ufshcd.c78
-rw-r--r--drivers/scsi/ufs/ufshcd.h9
-rw-r--r--drivers/soc/qcom/msm_smem.c6
-rw-r--r--include/linux/mfd/wcd934x/registers.h2
-rw-r--r--sound/soc/codecs/wcd9335.c4
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsd.c33
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsd.h1
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c108
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.c5
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 {