diff options
Diffstat (limited to 'sound/soc/codecs/wcd9xxx-resmgr-v2.c')
| -rw-r--r-- | sound/soc/codecs/wcd9xxx-resmgr-v2.c | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.c b/sound/soc/codecs/wcd9xxx-resmgr-v2.c index 9cd9736dc850..7ea1a93d7fb7 100644 --- a/sound/soc/codecs/wcd9xxx-resmgr-v2.c +++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.c @@ -14,11 +14,16 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/mfd/wcd9xxx/core.h> #include <linux/mfd/wcd9335/registers.h> +#include <linux/mfd/wcd934x/registers.h> #include <sound/soc.h> #include "wcd9xxx-resmgr-v2.h" #define WCD9XXX_RCO_CALIBRATION_DELAY_INC_US 5000 +#define WCD93XX_ANA_BIAS 0x0601 +#define WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41 +#define WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42 static const char *wcd_resmgr_clk_type_to_str(enum wcd_clock_type clk_type) { @@ -38,6 +43,15 @@ static int wcd_resmgr_codec_reg_update_bits(struct wcd9xxx_resmgr_v2 *resmgr, bool change; int ret; + if (resmgr->codec_type == WCD934X) { + /* Tavil does not support ANA_CLK_TOP register */ + if (reg == WCD9335_ANA_CLK_TOP) + return 0; + } else { + /* Tasha does not support CLK_SYS_MCLK_PRG register */ + if (reg == WCD934X_CLK_SYS_MCLK_PRG) + return 0; + } if (resmgr->codec) { ret = snd_soc_update_bits(resmgr->codec, reg, mask, val); } else if (resmgr->core_res->wcd_core_regmap) { @@ -59,6 +73,13 @@ static int wcd_resmgr_codec_reg_read(struct wcd9xxx_resmgr_v2 *resmgr, { int val, ret; + if (resmgr->codec_type == WCD934X) { + if (reg == WCD9335_ANA_CLK_TOP) + return 0; + } else { + if (reg == WCD934X_CLK_SYS_MCLK_PRG) + return 0; + } if (resmgr->codec) { val = snd_soc_read(resmgr->codec, reg); } else if (resmgr->core_res->wcd_core_regmap) { @@ -147,19 +168,19 @@ int wcd_resmgr_enable_master_bias(struct wcd9xxx_resmgr_v2 *resmgr) resmgr->master_bias_users++; if (resmgr->master_bias_users == 1) { - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, + wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BIAS, 0x80, 0x80); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, + wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BIAS, 0x40, 0x40); /* * 1ms delay is required after pre-charge is enabled * as per HW requirement */ usleep_range(1000, 1100); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, + wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BIAS, 0x40, 0x00); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, - 0x20, 0x00); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_ANA_BIAS, 0x20, 0x00); } pr_debug("%s: current master bias users: %d\n", __func__, @@ -183,10 +204,10 @@ int wcd_resmgr_disable_master_bias(struct wcd9xxx_resmgr_v2 *resmgr) resmgr->master_bias_users--; if (resmgr->master_bias_users == 0) { - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, + wcd_resmgr_codec_reg_update_bits(resmgr, WCD93XX_ANA_BIAS, 0x80, 0x00); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_BIAS, - 0x20, 0x00); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_ANA_BIAS, 0x20, 0x00); } mutex_unlock(&resmgr->master_bias_lock); return 0; @@ -212,19 +233,41 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) } if (++resmgr->clk_mclk_users == 1) { - - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, - 0x80, 0x80); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, - 0x08, 0x00); - wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, - 0x04, 0x04); wcd_resmgr_codec_reg_update_bits(resmgr, - WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, - 0x01, 0x01); + WCD9335_ANA_CLK_TOP, 0x80, 0x80); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD9335_ANA_CLK_TOP, 0x08, 0x00); wcd_resmgr_codec_reg_update_bits(resmgr, - WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL, + WCD9335_ANA_CLK_TOP, 0x04, 0x04); + if (resmgr->codec_type == WCD934X) { + /* + * In tavil clock contrl register is changed + * to CLK_SYS_MCLK_PRG + */ + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD934X_CLK_SYS_MCLK_PRG, 0x91, 0x91); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD934X_CODEC_RPM_CLK_MCLK_CFG, + 0x04, 0x04); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD934X_CODEC_RPM_CLK_GATE, 0x03, 0x00); + } else { + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x01, 0x01); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL, + 0x01, 0x01); + } /* * 10us sleep is required after clock is enabled * as per HW requirement @@ -259,6 +302,8 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr) wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP, 0x04, 0x00); + wcd_resmgr_codec_reg_update_bits(resmgr, + WCD934X_CLK_SYS_MCLK_PRG, 0x01, 0x0); resmgr->clk_type = WCD_CLK_OFF; } @@ -447,6 +492,7 @@ struct wcd9xxx_resmgr_v2 *wcd_resmgr_init( struct snd_soc_codec *codec) { struct wcd9xxx_resmgr_v2 *resmgr; + struct wcd9xxx *wcd9xxx; resmgr = kzalloc(sizeof(struct wcd9xxx_resmgr_v2), GFP_KERNEL); if (!resmgr) { @@ -454,6 +500,13 @@ struct wcd9xxx_resmgr_v2 *wcd_resmgr_init( return ERR_PTR(-ENOMEM); } + wcd9xxx = container_of(core_res, struct wcd9xxx, core_res); + if (!wcd9xxx) { + kfree(resmgr); + pr_err("%s: Cannot get wcd9xx pointer\n", __func__); + return ERR_PTR(-EINVAL); + } + mutex_init(&resmgr->codec_bg_clk_lock); mutex_init(&resmgr->master_bias_lock); resmgr->master_bias_users = 0; @@ -463,6 +516,7 @@ struct wcd9xxx_resmgr_v2 *wcd_resmgr_init( resmgr->codec = codec; resmgr->core_res = core_res; resmgr->sido_input_src = SIDO_SOURCE_INTERNAL; + resmgr->codec_type = wcd9xxx->type; return resmgr; } |
