|
@@ -225,15 +225,8 @@ struct wm_coeff_ctl_ops {
|
|
|
struct snd_ctl_elem_info *uinfo);
|
|
|
};
|
|
|
|
|
|
-struct wm_coeff {
|
|
|
- struct device *dev;
|
|
|
- struct list_head ctl_list;
|
|
|
- struct regmap *regmap;
|
|
|
-};
|
|
|
-
|
|
|
struct wm_coeff_ctl {
|
|
|
const char *name;
|
|
|
- struct snd_card *card;
|
|
|
struct wm_adsp_alg_region region;
|
|
|
struct wm_coeff_ctl_ops ops;
|
|
|
struct wm_adsp *adsp;
|
|
@@ -378,7 +371,6 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol,
|
|
|
static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
|
|
|
const void *buf, size_t len)
|
|
|
{
|
|
|
- struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
|
|
|
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
|
|
|
struct wm_adsp_alg_region *region = &ctl->region;
|
|
|
const struct wm_adsp_region *mem;
|
|
@@ -401,7 +393,7 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
|
|
|
if (!scratch)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- ret = regmap_raw_write(wm_coeff->regmap, reg, scratch,
|
|
|
+ ret = regmap_raw_write(adsp->regmap, reg, scratch,
|
|
|
ctl->len);
|
|
|
if (ret) {
|
|
|
adsp_err(adsp, "Failed to write %zu bytes to %x\n",
|
|
@@ -434,7 +426,6 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
|
|
|
static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
|
|
|
void *buf, size_t len)
|
|
|
{
|
|
|
- struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
|
|
|
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
|
|
|
struct wm_adsp_alg_region *region = &ctl->region;
|
|
|
const struct wm_adsp_region *mem;
|
|
@@ -457,7 +448,7 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
|
|
|
if (!scratch)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len);
|
|
|
+ ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
|
|
|
if (ret) {
|
|
|
adsp_err(adsp, "Failed to read %zu bytes from %x\n",
|
|
|
ctl->len, reg);
|
|
@@ -481,37 +472,18 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff,
|
|
|
- struct wm_coeff_ctl *ctl,
|
|
|
- const struct snd_kcontrol_new *kctl)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- struct snd_kcontrol *kcontrol;
|
|
|
-
|
|
|
- kcontrol = snd_ctl_new1(kctl, wm_coeff);
|
|
|
- ret = snd_ctl_add(ctl->card, kcontrol);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(wm_coeff->dev, "Failed to add %s: %d\n",
|
|
|
- kctl->name, ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
- ctl->kcontrol = kcontrol;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
struct wmfw_ctl_work {
|
|
|
- struct wm_coeff *wm_coeff;
|
|
|
+ struct wm_adsp *adsp;
|
|
|
struct wm_coeff_ctl *ctl;
|
|
|
struct work_struct work;
|
|
|
};
|
|
|
|
|
|
-static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
|
|
|
- struct wm_coeff_ctl *ctl)
|
|
|
+static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl)
|
|
|
{
|
|
|
struct snd_kcontrol_new *kcontrol;
|
|
|
int ret;
|
|
|
|
|
|
- if (!wm_coeff || !ctl || !ctl->name || !ctl->card)
|
|
|
+ if (!ctl || !ctl->name)
|
|
|
return -EINVAL;
|
|
|
|
|
|
kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
|
|
@@ -525,14 +497,17 @@ static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
|
|
|
kcontrol->put = wm_coeff_put;
|
|
|
kcontrol->private_value = (unsigned long)ctl;
|
|
|
|
|
|
- ret = wm_coeff_add_kcontrol(wm_coeff,
|
|
|
- ctl, kcontrol);
|
|
|
+ ret = snd_soc_add_card_controls(adsp->card,
|
|
|
+ kcontrol, 1);
|
|
|
if (ret < 0)
|
|
|
goto err_kcontrol;
|
|
|
|
|
|
kfree(kcontrol);
|
|
|
|
|
|
- list_add(&ctl->list, &wm_coeff->ctl_list);
|
|
|
+ ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card,
|
|
|
+ ctl->name);
|
|
|
+
|
|
|
+ list_add(&ctl->list, &adsp->ctl_list);
|
|
|
return 0;
|
|
|
|
|
|
err_kcontrol:
|
|
@@ -753,13 +728,12 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
|
|
|
+static int wm_coeff_init_control_caches(struct wm_adsp *adsp)
|
|
|
{
|
|
|
struct wm_coeff_ctl *ctl;
|
|
|
int ret;
|
|
|
|
|
|
- list_for_each_entry(ctl, &wm_coeff->ctl_list,
|
|
|
- list) {
|
|
|
+ list_for_each_entry(ctl, &adsp->ctl_list, list) {
|
|
|
if (!ctl->enabled || ctl->set)
|
|
|
continue;
|
|
|
ret = wm_coeff_read_control(ctl->kcontrol,
|
|
@@ -772,13 +746,12 @@ static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff)
|
|
|
+static int wm_coeff_sync_controls(struct wm_adsp *adsp)
|
|
|
{
|
|
|
struct wm_coeff_ctl *ctl;
|
|
|
int ret;
|
|
|
|
|
|
- list_for_each_entry(ctl, &wm_coeff->ctl_list,
|
|
|
- list) {
|
|
|
+ list_for_each_entry(ctl, &adsp->ctl_list, list) {
|
|
|
if (!ctl->enabled)
|
|
|
continue;
|
|
|
if (ctl->set) {
|
|
@@ -799,15 +772,14 @@ static void wm_adsp_ctl_work(struct work_struct *work)
|
|
|
struct wmfw_ctl_work,
|
|
|
work);
|
|
|
|
|
|
- wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl);
|
|
|
+ wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl);
|
|
|
kfree(ctl_work);
|
|
|
}
|
|
|
|
|
|
-static int wm_adsp_create_control(struct snd_soc_codec *codec,
|
|
|
+static int wm_adsp_create_control(struct wm_adsp *dsp,
|
|
|
const struct wm_adsp_alg_region *region)
|
|
|
|
|
|
{
|
|
|
- struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
|
|
|
struct wm_coeff_ctl *ctl;
|
|
|
struct wmfw_ctl_work *ctl_work;
|
|
|
char *name;
|
|
@@ -842,7 +814,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
|
|
|
snprintf(name, PAGE_SIZE, "DSP%d %s %x",
|
|
|
dsp->num, region_name, region->alg);
|
|
|
|
|
|
- list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
|
|
|
+ list_for_each_entry(ctl, &dsp->ctl_list,
|
|
|
list) {
|
|
|
if (!strcmp(ctl->name, name)) {
|
|
|
if (!ctl->enabled)
|
|
@@ -866,7 +838,6 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
|
|
|
ctl->set = 0;
|
|
|
ctl->ops.xget = wm_coeff_get;
|
|
|
ctl->ops.xput = wm_coeff_put;
|
|
|
- ctl->card = codec->card->snd_card;
|
|
|
ctl->adsp = dsp;
|
|
|
|
|
|
ctl->len = region->len;
|
|
@@ -882,7 +853,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
|
|
|
goto err_ctl_cache;
|
|
|
}
|
|
|
|
|
|
- ctl_work->wm_coeff = dsp->wm_coeff;
|
|
|
+ ctl_work->adsp = dsp;
|
|
|
ctl_work->ctl = ctl;
|
|
|
INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
|
|
|
schedule_work(&ctl_work->work);
|
|
@@ -903,7 +874,7 @@ err_name:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
+static int wm_adsp_setup_algs(struct wm_adsp *dsp)
|
|
|
{
|
|
|
struct regmap *regmap = dsp->regmap;
|
|
|
struct wmfw_adsp1_id_hdr adsp1_id;
|
|
@@ -1091,7 +1062,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
if (i + 1 < algs) {
|
|
|
region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
|
|
|
region->len -= be32_to_cpu(adsp1_alg[i].dm);
|
|
|
- wm_adsp_create_control(codec, region);
|
|
|
+ wm_adsp_create_control(dsp, region);
|
|
|
} else {
|
|
|
adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
|
|
|
be32_to_cpu(adsp1_alg[i].alg.id));
|
|
@@ -1108,7 +1079,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
if (i + 1 < algs) {
|
|
|
region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
|
|
|
region->len -= be32_to_cpu(adsp1_alg[i].zm);
|
|
|
- wm_adsp_create_control(codec, region);
|
|
|
+ wm_adsp_create_control(dsp, region);
|
|
|
} else {
|
|
|
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
|
|
be32_to_cpu(adsp1_alg[i].alg.id));
|
|
@@ -1137,7 +1108,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
if (i + 1 < algs) {
|
|
|
region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
|
|
|
region->len -= be32_to_cpu(adsp2_alg[i].xm);
|
|
|
- wm_adsp_create_control(codec, region);
|
|
|
+ wm_adsp_create_control(dsp, region);
|
|
|
} else {
|
|
|
adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
|
|
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
|
@@ -1154,7 +1125,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
if (i + 1 < algs) {
|
|
|
region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
|
|
|
region->len -= be32_to_cpu(adsp2_alg[i].ym);
|
|
|
- wm_adsp_create_control(codec, region);
|
|
|
+ wm_adsp_create_control(dsp, region);
|
|
|
} else {
|
|
|
adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
|
|
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
|
@@ -1171,7 +1142,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
|
|
|
if (i + 1 < algs) {
|
|
|
region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
|
|
|
region->len -= be32_to_cpu(adsp2_alg[i].zm);
|
|
|
- wm_adsp_create_control(codec, region);
|
|
|
+ wm_adsp_create_control(dsp, region);
|
|
|
} else {
|
|
|
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
|
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
|
@@ -1391,6 +1362,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|
|
int ret;
|
|
|
int val;
|
|
|
|
|
|
+ dsp->card = codec->card;
|
|
|
+
|
|
|
switch (event) {
|
|
|
case SND_SOC_DAPM_POST_PMU:
|
|
|
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
|
|
@@ -1425,7 +1398,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
|
- ret = wm_adsp_setup_algs(dsp, codec);
|
|
|
+ ret = wm_adsp_setup_algs(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
@@ -1434,12 +1407,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|
|
goto err;
|
|
|
|
|
|
/* Initialize caches for enabled and unset controls */
|
|
|
- ret = wm_coeff_init_control_caches(dsp->wm_coeff);
|
|
|
+ ret = wm_coeff_init_control_caches(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
|
/* Sync set controls */
|
|
|
- ret = wm_coeff_sync_controls(dsp->wm_coeff);
|
|
|
+ ret = wm_coeff_sync_controls(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
@@ -1460,10 +1433,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
|
|
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
|
|
|
ADSP1_SYS_ENA, 0);
|
|
|
|
|
|
- list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
|
|
|
- list) {
|
|
|
+ list_for_each_entry(ctl, &dsp->ctl_list, list)
|
|
|
ctl->enabled = 0;
|
|
|
- }
|
|
|
break;
|
|
|
|
|
|
default:
|
|
@@ -1520,6 +1491,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|
|
unsigned int val;
|
|
|
int ret;
|
|
|
|
|
|
+ dsp->card = codec->card;
|
|
|
+
|
|
|
switch (event) {
|
|
|
case SND_SOC_DAPM_POST_PMU:
|
|
|
/*
|
|
@@ -1582,7 +1555,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
|
- ret = wm_adsp_setup_algs(dsp, codec);
|
|
|
+ ret = wm_adsp_setup_algs(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
@@ -1591,12 +1564,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|
|
goto err;
|
|
|
|
|
|
/* Initialize caches for enabled and unset controls */
|
|
|
- ret = wm_coeff_init_control_caches(dsp->wm_coeff);
|
|
|
+ ret = wm_coeff_init_control_caches(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
|
/* Sync set controls */
|
|
|
- ret = wm_coeff_sync_controls(dsp->wm_coeff);
|
|
|
+ ret = wm_coeff_sync_controls(dsp);
|
|
|
if (ret != 0)
|
|
|
goto err;
|
|
|
|
|
@@ -1637,10 +1610,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
|
|
|
ret);
|
|
|
}
|
|
|
|
|
|
- list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
|
|
|
- list) {
|
|
|
+ list_for_each_entry(ctl, &dsp->ctl_list, list)
|
|
|
ctl->enabled = 0;
|
|
|
- }
|
|
|
|
|
|
while (!list_empty(&dsp->alg_regions)) {
|
|
|
alg_region = list_first_entry(&dsp->alg_regions,
|
|
@@ -1679,49 +1650,38 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
|
|
|
}
|
|
|
|
|
|
INIT_LIST_HEAD(&adsp->alg_regions);
|
|
|
-
|
|
|
- adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff),
|
|
|
- GFP_KERNEL);
|
|
|
- if (!adsp->wm_coeff)
|
|
|
- return -ENOMEM;
|
|
|
- adsp->wm_coeff->regmap = adsp->regmap;
|
|
|
- adsp->wm_coeff->dev = adsp->dev;
|
|
|
- INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list);
|
|
|
+ INIT_LIST_HEAD(&adsp->ctl_list);
|
|
|
|
|
|
if (dvfs) {
|
|
|
adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
|
|
|
if (IS_ERR(adsp->dvfs)) {
|
|
|
ret = PTR_ERR(adsp->dvfs);
|
|
|
dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
|
|
|
- goto out_coeff;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
ret = regulator_enable(adsp->dvfs);
|
|
|
if (ret != 0) {
|
|
|
dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
|
|
|
ret);
|
|
|
- goto out_coeff;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
|
|
|
if (ret != 0) {
|
|
|
dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
|
|
|
ret);
|
|
|
- goto out_coeff;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
ret = regulator_disable(adsp->dvfs);
|
|
|
if (ret != 0) {
|
|
|
dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
|
|
|
ret);
|
|
|
- goto out_coeff;
|
|
|
+ return ret;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
-
|
|
|
-out_coeff:
|
|
|
- kfree(adsp->wm_coeff);
|
|
|
- return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(wm_adsp2_init);
|