Skip to content

Commit 73ecf1a

Browse files
charleskeepaxbroonie
authored andcommitted
ASoC: wm_adsp: Correct cache handling of new kernel control API
The recently added API that exposes firmware mixer controls to the kernel is missing cache handling and all writes bypass the cache, this obviously causes the cache to get out of sync with the hardware. Factor out the cache handling into two new helper functions and call those from both the normal ALSA control handlers and the new kernel API. Fixes: eb65ccd ("ASoC: wm_adsp: Expose mixer control API") Signed-off-by: Charles Keepax <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 85578bb commit 73ecf1a

File tree

1 file changed

+51
-47
lines changed

1 file changed

+51
-47
lines changed

sound/soc/codecs/wm_adsp.c

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,8 +1030,8 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
10301030
return -ETIMEDOUT;
10311031
}
10321032

1033-
static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
1034-
const void *buf, size_t len)
1033+
static int wm_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
1034+
const void *buf, size_t len)
10351035
{
10361036
struct wm_adsp *dsp = ctl->dsp;
10371037
void *scratch;
@@ -1061,6 +1061,23 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
10611061
return 0;
10621062
}
10631063

1064+
static int wm_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
1065+
const void *buf, size_t len)
1066+
{
1067+
int ret = 0;
1068+
1069+
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1070+
ret = -EPERM;
1071+
else if (buf != ctl->cache)
1072+
memcpy(ctl->cache, buf, len);
1073+
1074+
ctl->set = 1;
1075+
if (ctl->enabled && ctl->dsp->running)
1076+
ret = wm_coeff_write_ctrl_raw(ctl, buf, len);
1077+
1078+
return ret;
1079+
}
1080+
10641081
static int wm_coeff_put(struct snd_kcontrol *kctl,
10651082
struct snd_ctl_elem_value *ucontrol)
10661083
{
@@ -1071,16 +1088,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,
10711088
int ret = 0;
10721089

10731090
mutex_lock(&ctl->dsp->pwr_lock);
1074-
1075-
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1076-
ret = -EPERM;
1077-
else
1078-
memcpy(ctl->cache, p, ctl->len);
1079-
1080-
ctl->set = 1;
1081-
if (ctl->enabled && ctl->dsp->running)
1082-
ret = wm_coeff_write_control(ctl, p, ctl->len);
1083-
1091+
ret = wm_coeff_write_ctrl(ctl, p, ctl->len);
10841092
mutex_unlock(&ctl->dsp->pwr_lock);
10851093

10861094
return ret;
@@ -1096,15 +1104,10 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
10961104

10971105
mutex_lock(&ctl->dsp->pwr_lock);
10981106

1099-
if (copy_from_user(ctl->cache, bytes, size)) {
1107+
if (copy_from_user(ctl->cache, bytes, size))
11001108
ret = -EFAULT;
1101-
} else {
1102-
ctl->set = 1;
1103-
if (ctl->enabled && ctl->dsp->running)
1104-
ret = wm_coeff_write_control(ctl, ctl->cache, size);
1105-
else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1106-
ret = -EPERM;
1107-
}
1109+
else
1110+
ret = wm_coeff_write_ctrl(ctl, ctl->cache, size);
11081111

11091112
mutex_unlock(&ctl->dsp->pwr_lock);
11101113

@@ -1135,8 +1138,8 @@ static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
11351138
return ret;
11361139
}
11371140

1138-
static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
1139-
void *buf, size_t len)
1141+
static int wm_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
1142+
void *buf, size_t len)
11401143
{
11411144
struct wm_adsp *dsp = ctl->dsp;
11421145
void *scratch;
@@ -1166,29 +1169,37 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
11661169
return 0;
11671170
}
11681171

1169-
static int wm_coeff_get(struct snd_kcontrol *kctl,
1170-
struct snd_ctl_elem_value *ucontrol)
1172+
static int wm_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
11711173
{
1172-
struct soc_bytes_ext *bytes_ext =
1173-
(struct soc_bytes_ext *)kctl->private_value;
1174-
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1175-
char *p = ucontrol->value.bytes.data;
11761174
int ret = 0;
11771175

1178-
mutex_lock(&ctl->dsp->pwr_lock);
1179-
11801176
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
11811177
if (ctl->enabled && ctl->dsp->running)
1182-
ret = wm_coeff_read_control(ctl, p, ctl->len);
1178+
return wm_coeff_read_ctrl_raw(ctl, buf, len);
11831179
else
1184-
ret = -EPERM;
1180+
return -EPERM;
11851181
} else {
11861182
if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1187-
ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1183+
ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
11881184

1189-
memcpy(p, ctl->cache, ctl->len);
1185+
if (buf != ctl->cache)
1186+
memcpy(buf, ctl->cache, len);
11901187
}
11911188

1189+
return ret;
1190+
}
1191+
1192+
static int wm_coeff_get(struct snd_kcontrol *kctl,
1193+
struct snd_ctl_elem_value *ucontrol)
1194+
{
1195+
struct soc_bytes_ext *bytes_ext =
1196+
(struct soc_bytes_ext *)kctl->private_value;
1197+
struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1198+
char *p = ucontrol->value.bytes.data;
1199+
int ret;
1200+
1201+
mutex_lock(&ctl->dsp->pwr_lock);
1202+
ret = wm_coeff_read_ctrl(ctl, p, ctl->len);
11921203
mutex_unlock(&ctl->dsp->pwr_lock);
11931204

11941205
return ret;
@@ -1204,15 +1215,7 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
12041215

12051216
mutex_lock(&ctl->dsp->pwr_lock);
12061217

1207-
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1208-
if (ctl->enabled && ctl->dsp->running)
1209-
ret = wm_coeff_read_control(ctl, ctl->cache, size);
1210-
else
1211-
ret = -EPERM;
1212-
} else {
1213-
if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1214-
ret = wm_coeff_read_control(ctl, ctl->cache, size);
1215-
}
1218+
ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, size);
12161219

12171220
if (!ret && copy_to_user(bytes, ctl->cache, size))
12181221
ret = -EFAULT;
@@ -1340,7 +1343,7 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
13401343
* created so we don't need to do anything.
13411344
*/
13421345
if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
1343-
ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1346+
ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
13441347
if (ret < 0)
13451348
return ret;
13461349
}
@@ -1358,7 +1361,8 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
13581361
if (!ctl->enabled)
13591362
continue;
13601363
if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1361-
ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
1364+
ret = wm_coeff_write_ctrl_raw(ctl, ctl->cache,
1365+
ctl->len);
13621366
if (ret < 0)
13631367
return ret;
13641368
}
@@ -2048,7 +2052,7 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
20482052
if (len > ctl->len)
20492053
return -EINVAL;
20502054

2051-
ret = wm_coeff_write_control(ctl, buf, len);
2055+
ret = wm_coeff_write_ctrl(ctl, buf, len);
20522056

20532057
kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl->name);
20542058
snd_ctl_notify(dsp->component->card->snd_card,
@@ -2070,7 +2074,7 @@ int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
20702074
if (len > ctl->len)
20712075
return -EINVAL;
20722076

2073-
return wm_coeff_read_control(ctl, buf, len);
2077+
return wm_coeff_read_ctrl(ctl, buf, len);
20742078
}
20752079
EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
20762080

0 commit comments

Comments
 (0)