ASoC: wcd9xxx: Handle codec specific clock enable post ssr

Clock enablement depends on the codec type. Handle the
clock enablement after subsystem-restart depending on the
type of the codec.

Change-Id: Ic0b5504c02f816488fe2f33837200783520b6993
Signed-off-by: Phani Kumar Uppalapati <phaniu@codeaurora.org>
This commit is contained in:
Phani Kumar Uppalapati 2014-12-06 17:36:19 -08:00
parent ac6fe126ae
commit 4894eefac0
6 changed files with 49 additions and 6 deletions

View File

@ -3344,7 +3344,7 @@ static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
core_res = &msm8x10_wcd->wcd9xxx_res;
ret = wcd9xxx_resmgr_init(&msm8x10_wcd_priv->resmgr,
codec, core_res, NULL, &pdata->micbias,
NULL, WCD9XXX_CDC_TYPE_HELICON);
NULL, NULL, WCD9XXX_CDC_TYPE_HELICON);
if (ret) {
dev_err(codec->dev,
"%s: wcd9xxx init failed %d\n",

View File

@ -6401,7 +6401,7 @@ static int tapan_codec_probe(struct snd_soc_codec *codec)
pdata = dev_get_platdata(codec->dev->parent);
ret = wcd9xxx_resmgr_init(&tapan->resmgr, codec, core_res, pdata,
&pdata->micbias, &tapan_reg_address,
WCD9XXX_CDC_TYPE_TAPAN);
NULL, WCD9XXX_CDC_TYPE_TAPAN);
if (ret) {
pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
return ret;

View File

@ -7359,7 +7359,7 @@ static int taiko_codec_probe(struct snd_soc_codec *codec)
pdata = dev_get_platdata(codec->dev->parent);
ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, core_res, pdata,
&pdata->micbias, &taiko_reg_address,
WCD9XXX_CDC_TYPE_TAIKO);
NULL, WCD9XXX_CDC_TYPE_TAIKO);
if (ret) {
pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
goto err_init;

View File

@ -8479,6 +8479,10 @@ static int tomtom_codec_vote_max_bw(struct snd_soc_codec *codec,
bw_ops, true);
}
static const struct wcd9xxx_resmgr_cb resmgr_cb = {
.cdc_rco_ctrl = tomtom_codec_internal_rco_ctrl,
};
static const struct wcd_cpe_cdc_cb cpe_cb = {
.cdc_clk_en = tomtom_codec_internal_rco_ctrl,
.cpe_clk_en = tomtom_codec_fll_enable,
@ -8556,7 +8560,7 @@ static int tomtom_codec_probe(struct snd_soc_codec *codec)
pdata = dev_get_platdata(codec->dev->parent);
ret = wcd9xxx_resmgr_init(&tomtom->resmgr, codec, core_res, pdata,
&pdata->micbias, &tomtom_reg_address,
WCD9XXX_CDC_TYPE_TOMTOM);
&resmgr_cb, WCD9XXX_CDC_TYPE_TOMTOM);
if (ret) {
pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
goto err_nomem_slimch;

View File

@ -234,6 +234,25 @@ static void wcd9xxx_disable_clock_block(struct wcd9xxx_resmgr *resmgr)
pr_debug("%s: leave\n", __func__);
}
static void wcd9xxx_resmgr_cdc_specific_get_clk(struct wcd9xxx_resmgr *resmgr,
int clk_users)
{
/* Caller of this funcion should have acquired
* BG_CLK lock
*/
WCD9XXX_BG_CLK_UNLOCK(resmgr);
if (clk_users) {
if (resmgr->resmgr_cb &&
resmgr->resmgr_cb->cdc_rco_ctrl) {
while (clk_users--)
resmgr->resmgr_cb->cdc_rco_ctrl(resmgr->codec,
true);
}
}
/* Acquire BG_CLK lock before return */
WCD9XXX_BG_CLK_LOCK(resmgr);
}
void wcd9xxx_resmgr_post_ssr(struct wcd9xxx_resmgr *resmgr)
{
int old_bg_audio_users, old_bg_mbhc_users;
@ -270,9 +289,12 @@ void wcd9xxx_resmgr_post_ssr(struct wcd9xxx_resmgr *resmgr)
wcd9xxx_resmgr_get_clk_block(resmgr, WCD9XXX_CLK_MCLK);
}
if (old_clk_rco_users) {
if (resmgr->codec_type == WCD9XXX_CDC_TYPE_TOMTOM) {
wcd9xxx_resmgr_cdc_specific_get_clk(resmgr, old_clk_rco_users);
} else if (old_clk_rco_users) {
while (old_clk_rco_users--)
wcd9xxx_resmgr_get_clk_block(resmgr, WCD9XXX_CLK_RCO);
wcd9xxx_resmgr_get_clk_block(resmgr,
WCD9XXX_CLK_RCO);
}
WCD9XXX_BG_CLK_UNLOCK(resmgr);
pr_debug("%s: leave\n", __func__);
@ -645,6 +667,8 @@ void wcd9xxx_resmgr_get_clk_block(struct wcd9xxx_resmgr *resmgr,
resmgr->clk_type == WCD9XXX_CLK_RCO) {
/* RCO to MCLK switch, with RCO still powered on */
if (resmgr->codec_type == WCD9XXX_CDC_TYPE_TOMTOM) {
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_PRE_MCLK_ON);
snd_soc_update_bits(codec,
WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
0x40, 0x00);
@ -655,6 +679,8 @@ void wcd9xxx_resmgr_get_clk_block(struct wcd9xxx_resmgr *resmgr,
snd_soc_update_bits(codec,
WCD9XXX_A_CLK_BUFF_EN1,
0x08, 0x00);
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_POST_MCLK_ON);
} else {
/* if RCO is enabled, switch from it */
WARN_ON(!(snd_soc_read(resmgr->codec,
@ -741,12 +767,16 @@ void wcd9xxx_resmgr_put_clk_block(struct wcd9xxx_resmgr *resmgr,
WCD9XXX_A_CLK_BUFF_EN1,
0x01, 0x00);
} else {
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_PRE_MCLK_OFF);
snd_soc_update_bits(codec,
WCD9XXX_A_CLK_BUFF_EN1,
0x08, 0x08);
snd_soc_update_bits(codec,
WCD9XXX_A_CLK_BUFF_EN1,
0x01, 0x00);
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_POST_MCLK_OFF);
}
} else {
/* disable clock */
@ -1034,6 +1064,7 @@ int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
struct wcd9xxx_pdata *pdata,
struct wcd9xxx_micbias_setting *micbias_pdata,
struct wcd9xxx_reg_address *reg_addr,
const struct wcd9xxx_resmgr_cb *resmgr_cb,
enum wcd9xxx_cdc_type cdc_type)
{
WARN(ARRAY_SIZE(wcd9xxx_event_string) != WCD9XXX_EVENT_LAST + 1,
@ -1048,6 +1079,7 @@ int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
resmgr->pdata = pdata;
resmgr->micbias_pdata = micbias_pdata;
resmgr->reg_addr = reg_addr;
resmgr->resmgr_cb = resmgr_cb;
INIT_LIST_HEAD(&resmgr->update_bit_cond_h);

View File

@ -118,6 +118,10 @@ enum wcd9xxx_notify_event {
WCD9XXX_EVENT_LAST,
};
struct wcd9xxx_resmgr_cb {
int (*cdc_rco_ctrl)(struct snd_soc_codec *, bool);
};
struct wcd9xxx_resmgr {
struct snd_soc_codec *codec;
struct wcd9xxx_core_resource *core_res;
@ -169,6 +173,8 @@ struct wcd9xxx_resmgr {
struct mutex codec_bg_clk_lock;
enum wcd9xxx_cdc_type codec_type;
const struct wcd9xxx_resmgr_cb *resmgr_cb;
};
int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
@ -177,6 +183,7 @@ int wcd9xxx_resmgr_init(struct wcd9xxx_resmgr *resmgr,
struct wcd9xxx_pdata *pdata,
struct wcd9xxx_micbias_setting *micbias_pdata,
struct wcd9xxx_reg_address *reg_addr,
const struct wcd9xxx_resmgr_cb *resmgr_cb,
enum wcd9xxx_cdc_type cdc_type);
void wcd9xxx_resmgr_deinit(struct wcd9xxx_resmgr *resmgr);