Merge "soc: swr-wcd-ctrl: Fix wsa mute issue for stereo playback"

This commit is contained in:
Linux Build Service Account 2018-09-26 10:39:53 -07:00 committed by Gerrit - the friendly Code Review server
commit 997c89933a
2 changed files with 34 additions and 13 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -1727,6 +1727,8 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
(swrm->state == SWR_MSTR_UP)) { (swrm->state == SWR_MSTR_UP)) {
dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n", dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
__func__, swrm->state); __func__, swrm->state);
list_for_each_entry(swr_dev, &mstr->devices, dev_list)
swr_reset_device(swr_dev);
} else { } else {
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev);
mutex_unlock(&swrm->reslock); mutex_unlock(&swrm->reslock);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -76,6 +76,7 @@ struct swr_port {
enum { enum {
WSA881X_DEV_DOWN, WSA881X_DEV_DOWN,
WSA881X_DEV_UP, WSA881X_DEV_UP,
WSA881X_DEV_READY,
}; };
/* /*
@ -99,6 +100,7 @@ struct wsa881x_priv {
int version; int version;
struct mutex bg_lock; struct mutex bg_lock;
struct mutex res_lock; struct mutex res_lock;
struct mutex temp_lock;
struct snd_info_entry *entry; struct snd_info_entry *entry;
struct snd_info_entry *version_entry; struct snd_info_entry *version_entry;
int state; int state;
@ -464,6 +466,17 @@ static const struct file_operations codec_debug_ops = {
.read = codec_debug_read, .read = codec_debug_read,
}; };
static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
{
mutex_lock(&wsa881x->res_lock);
if (wsa881x->state != WSA881X_DEV_READY) {
regcache_mark_dirty(wsa881x->regmap);
regcache_sync(wsa881x->regmap);
wsa881x->state = WSA881X_DEV_READY;
}
mutex_unlock(&wsa881x->res_lock);
}
static const struct reg_sequence wsa881x_pre_pmu_pa[] = { static const struct reg_sequence wsa881x_pre_pmu_pa[] = {
{WSA881X_SPKR_DRV_GAIN, 0x41, 0}, {WSA881X_SPKR_DRV_GAIN, 0x41, 0},
{WSA881X_SPKR_MISC_CTL1, 0x01, 0}, {WSA881X_SPKR_MISC_CTL1, 0x01, 0},
@ -790,7 +803,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE); wsa881x_resource_acquire(codec, ENABLE);
mutex_unlock(&wsa881x->temp_lock);
wsa881x_boost_ctrl(codec, ENABLE); wsa881x_boost_ctrl(codec, ENABLE);
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
@ -798,7 +813,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
wsa881x->swr_slave->dev_num, wsa881x->swr_slave->dev_num,
false); false);
wsa881x_boost_ctrl(codec, DISABLE); wsa881x_boost_ctrl(codec, DISABLE);
mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE);
mutex_unlock(&wsa881x->temp_lock);
break; break;
} }
return 0; return 0;
@ -1042,13 +1059,8 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
return -EINVAL; return -EINVAL;
} }
} }
mutex_lock(&wsa881x->res_lock); wsa881x_regcache_sync(wsa881x);
if (!wsa881x->clk_cnt) { mutex_lock(&wsa881x->temp_lock);
regcache_mark_dirty(wsa881x->regmap);
regcache_sync(wsa881x->regmap);
}
mutex_unlock(&wsa881x->res_lock);
wsa881x_resource_acquire(codec, ENABLE); wsa881x_resource_acquire(codec, ENABLE);
snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00); snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
@ -1061,6 +1073,7 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4); wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4);
wsa881x_resource_acquire(codec, DISABLE); wsa881x_resource_acquire(codec, DISABLE);
mutex_unlock(&wsa881x->temp_lock);
return 0; return 0;
} }
@ -1076,7 +1089,6 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
dev = wsa881x->swr_slave; dev = wsa881x->swr_slave;
wsa881x->codec = codec; wsa881x->codec = codec;
mutex_init(&wsa881x->bg_lock); mutex_init(&wsa881x->bg_lock);
mutex_init(&wsa881x->res_lock);
wsa881x_init(codec); wsa881x_init(codec);
snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name), snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name),
"%s.%x", "wsatz", (u8)dev->addr); "%s.%x", "wsatz", (u8)dev->addr);
@ -1098,7 +1110,6 @@ static int wsa881x_remove(struct snd_soc_codec *codec)
if (wsa881x->tz_pdata.tz_dev) if (wsa881x->tz_pdata.tz_dev)
wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev); wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
mutex_destroy(&wsa881x->bg_lock); mutex_destroy(&wsa881x->bg_lock);
mutex_destroy(&wsa881x->res_lock);
return 0; return 0;
} }
@ -1224,6 +1235,8 @@ static int wsa881x_swr_probe(struct swr_device *pdev)
if (wsa881x->wsa_rst_np) if (wsa881x->wsa_rst_np)
pin_state_current = msm_cdc_pinctrl_get_state( pin_state_current = msm_cdc_pinctrl_get_state(
wsa881x->wsa_rst_np); wsa881x->wsa_rst_np);
mutex_init(&wsa881x->res_lock);
mutex_init(&wsa881x->temp_lock);
wsa881x_gpio_ctrl(wsa881x, true); wsa881x_gpio_ctrl(wsa881x, true);
wsa881x->state = WSA881X_DEV_UP; wsa881x->state = WSA881X_DEV_UP;
@ -1303,6 +1316,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev)
return -EINVAL; return -EINVAL;
} }
debugfs_remove_recursive(debugfs_wsa881x_dent); debugfs_remove_recursive(debugfs_wsa881x_dent);
mutex_destroy(&wsa881x->res_lock);
mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
if (wsa881x->pd_gpio) if (wsa881x->pd_gpio)
gpio_free(wsa881x->pd_gpio); gpio_free(wsa881x->pd_gpio);
@ -1361,6 +1376,11 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__); dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (wsa881x->state == WSA881X_DEV_READY) {
dev_dbg(&pdev->dev, "%s: device already active\n", __func__);
return 0;
}
wsa881x->bg_cnt = 0; wsa881x->bg_cnt = 0;
wsa881x->clk_cnt = 0; wsa881x->clk_cnt = 0;
while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) { while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
@ -1368,8 +1388,7 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
usleep_range(1000, 1100); usleep_range(1000, 1100);
} }
pdev->dev_num = devnum; pdev->dev_num = devnum;
regcache_mark_dirty(wsa881x->regmap); wsa881x_regcache_sync(wsa881x);
regcache_sync(wsa881x->regmap);
return 0; return 0;
} }