|
@@ -77,6 +77,7 @@ struct swr_port {
|
|
|
enum {
|
|
|
WSA881X_DEV_DOWN,
|
|
|
WSA881X_DEV_UP,
|
|
|
+ WSA881X_DEV_READY,
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -100,6 +101,7 @@ struct wsa881x_priv {
|
|
|
int version;
|
|
|
struct mutex bg_lock;
|
|
|
struct mutex res_lock;
|
|
|
+ struct mutex temp_lock;
|
|
|
struct snd_info_entry *entry;
|
|
|
struct snd_info_entry *version_entry;
|
|
|
int state;
|
|
@@ -492,6 +494,17 @@ static const struct file_operations codec_debug_ops = {
|
|
|
.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[] = {
|
|
|
{WSA881X_SPKR_DRV_GAIN, 0x41, 0},
|
|
|
{WSA881X_SPKR_MISC_CTL1, 0x01, 0},
|
|
@@ -870,7 +883,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|
|
|
|
|
switch (event) {
|
|
|
case SND_SOC_DAPM_PRE_PMU:
|
|
|
+ mutex_lock(&wsa881x->temp_lock);
|
|
|
wsa881x_resource_acquire(codec, ENABLE);
|
|
|
+ mutex_unlock(&wsa881x->temp_lock);
|
|
|
wsa881x_boost_ctrl(codec, ENABLE);
|
|
|
break;
|
|
|
case SND_SOC_DAPM_POST_PMD:
|
|
@@ -878,7 +893,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
|
|
|
wsa881x->swr_slave->dev_num,
|
|
|
false);
|
|
|
wsa881x_boost_ctrl(codec, DISABLE);
|
|
|
+ mutex_lock(&wsa881x->temp_lock);
|
|
|
wsa881x_resource_acquire(codec, DISABLE);
|
|
|
+ mutex_unlock(&wsa881x->temp_lock);
|
|
|
break;
|
|
|
}
|
|
|
return 0;
|
|
@@ -1126,13 +1143,8 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
}
|
|
|
- mutex_lock(&wsa881x->res_lock);
|
|
|
- if (!wsa881x->clk_cnt) {
|
|
|
- regcache_mark_dirty(wsa881x->regmap);
|
|
|
- regcache_sync(wsa881x->regmap);
|
|
|
- }
|
|
|
- mutex_unlock(&wsa881x->res_lock);
|
|
|
-
|
|
|
+ wsa881x_regcache_sync(wsa881x);
|
|
|
+ mutex_lock(&wsa881x->temp_lock);
|
|
|
wsa881x_resource_acquire(codec, ENABLE);
|
|
|
|
|
|
snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
|
|
@@ -1145,6 +1157,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);
|
|
|
|
|
|
wsa881x_resource_acquire(codec, DISABLE);
|
|
|
+ mutex_unlock(&wsa881x->temp_lock);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1160,7 +1173,6 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
|
|
|
dev = wsa881x->swr_slave;
|
|
|
wsa881x->codec = codec;
|
|
|
mutex_init(&wsa881x->bg_lock);
|
|
|
- mutex_init(&wsa881x->res_lock);
|
|
|
wsa881x_init(codec);
|
|
|
snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name),
|
|
|
"%s.%x", "wsatz", (u8)dev->addr);
|
|
@@ -1182,7 +1194,6 @@ static int wsa881x_remove(struct snd_soc_codec *codec)
|
|
|
if (wsa881x->tz_pdata.tz_dev)
|
|
|
wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
|
|
|
mutex_destroy(&wsa881x->bg_lock);
|
|
|
- mutex_destroy(&wsa881x->res_lock);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1365,6 +1376,8 @@ static int wsa881x_swr_probe(struct swr_device *pdev)
|
|
|
__func__);
|
|
|
goto dev_err;
|
|
|
}
|
|
|
+ mutex_init(&wsa881x->res_lock);
|
|
|
+ mutex_init(&wsa881x->temp_lock);
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -1387,6 +1400,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev)
|
|
|
}
|
|
|
debugfs_remove_recursive(debugfs_wsa881x_dent);
|
|
|
debugfs_wsa881x_dent = NULL;
|
|
|
+ mutex_destroy(&wsa881x->res_lock);
|
|
|
+ mutex_destroy(&wsa881x->temp_lock);
|
|
|
snd_soc_unregister_codec(&pdev->dev);
|
|
|
if (wsa881x->pd_gpio)
|
|
|
gpio_free(wsa881x->pd_gpio);
|
|
@@ -1445,6 +1460,11 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
|
|
|
dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__);
|
|
|
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->clk_cnt = 0;
|
|
|
while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
|
|
@@ -1452,8 +1472,8 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
|
|
|
usleep_range(1000, 1100);
|
|
|
}
|
|
|
pdev->dev_num = devnum;
|
|
|
- regcache_mark_dirty(wsa881x->regmap);
|
|
|
- regcache_sync(wsa881x->regmap);
|
|
|
+ wsa881x_regcache_sync(wsa881x);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|