mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 23:21:46 +00:00
ASoC: wm_adsp: Add support for DSP control flags
The DSP control information contains various hints about the usage of the control use these when handling the control. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
8299ee8123
commit
26c22a1922
2 changed files with 40 additions and 8 deletions
|
@ -240,6 +240,7 @@ struct wm_coeff_ctl {
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned int set:1;
|
unsigned int set:1;
|
||||||
struct snd_kcontrol *kcontrol;
|
struct snd_kcontrol *kcontrol;
|
||||||
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
|
||||||
|
@ -472,7 +473,15 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
|
||||||
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
|
struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
|
||||||
char *p = ucontrol->value.bytes.data;
|
char *p = ucontrol->value.bytes.data;
|
||||||
|
|
||||||
|
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
|
||||||
|
if (ctl->enabled)
|
||||||
|
return wm_coeff_read_control(ctl, p, ctl->len);
|
||||||
|
else
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(p, ctl->cache, ctl->len);
|
memcpy(p, ctl->cache, ctl->len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,6 +510,15 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
|
||||||
kcontrol->put = wm_coeff_put;
|
kcontrol->put = wm_coeff_put;
|
||||||
kcontrol->private_value = (unsigned long)ctl;
|
kcontrol->private_value = (unsigned long)ctl;
|
||||||
|
|
||||||
|
if (ctl->flags) {
|
||||||
|
if (ctl->flags & WMFW_CTL_FLAG_WRITEABLE)
|
||||||
|
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||||
|
if (ctl->flags & WMFW_CTL_FLAG_READABLE)
|
||||||
|
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ;
|
||||||
|
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
|
||||||
|
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
|
||||||
|
}
|
||||||
|
|
||||||
ret = snd_soc_add_card_controls(dsp->card,
|
ret = snd_soc_add_card_controls(dsp->card,
|
||||||
kcontrol, 1);
|
kcontrol, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -526,6 +544,9 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
|
||||||
list_for_each_entry(ctl, &dsp->ctl_list, list) {
|
list_for_each_entry(ctl, &dsp->ctl_list, list) {
|
||||||
if (!ctl->enabled || ctl->set)
|
if (!ctl->enabled || ctl->set)
|
||||||
continue;
|
continue;
|
||||||
|
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
|
||||||
|
continue;
|
||||||
|
|
||||||
ret = wm_coeff_read_control(ctl,
|
ret = wm_coeff_read_control(ctl,
|
||||||
ctl->cache,
|
ctl->cache,
|
||||||
ctl->len);
|
ctl->len);
|
||||||
|
@ -544,7 +565,7 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
|
||||||
list_for_each_entry(ctl, &dsp->ctl_list, list) {
|
list_for_each_entry(ctl, &dsp->ctl_list, list) {
|
||||||
if (!ctl->enabled)
|
if (!ctl->enabled)
|
||||||
continue;
|
continue;
|
||||||
if (ctl->set) {
|
if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
|
||||||
ret = wm_coeff_write_control(ctl,
|
ret = wm_coeff_write_control(ctl,
|
||||||
ctl->cache,
|
ctl->cache,
|
||||||
ctl->len);
|
ctl->len);
|
||||||
|
@ -569,7 +590,8 @@ static void wm_adsp_ctl_work(struct work_struct *work)
|
||||||
static int wm_adsp_create_control(struct wm_adsp *dsp,
|
static int wm_adsp_create_control(struct wm_adsp *dsp,
|
||||||
const struct wm_adsp_alg_region *alg_region,
|
const struct wm_adsp_alg_region *alg_region,
|
||||||
unsigned int offset, unsigned int len,
|
unsigned int offset, unsigned int len,
|
||||||
const char *subname, unsigned int subname_len)
|
const char *subname, unsigned int subname_len,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct wm_coeff_ctl *ctl;
|
struct wm_coeff_ctl *ctl;
|
||||||
struct wmfw_ctl_work *ctl_work;
|
struct wmfw_ctl_work *ctl_work;
|
||||||
|
@ -577,6 +599,9 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
|
||||||
char *region_name;
|
char *region_name;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (flags & WMFW_CTL_FLAG_SYS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (alg_region->type) {
|
switch (alg_region->type) {
|
||||||
case WMFW_ADSP1_PM:
|
case WMFW_ADSP1_PM:
|
||||||
region_name = "PM";
|
region_name = "PM";
|
||||||
|
@ -649,6 +674,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
|
||||||
ctl->ops.xput = wm_coeff_put;
|
ctl->ops.xput = wm_coeff_put;
|
||||||
ctl->dsp = dsp;
|
ctl->dsp = dsp;
|
||||||
|
|
||||||
|
ctl->flags = flags;
|
||||||
ctl->offset = offset;
|
ctl->offset = offset;
|
||||||
if (len > 512) {
|
if (len > 512) {
|
||||||
adsp_warn(dsp, "Truncating control %s from %d\n",
|
adsp_warn(dsp, "Truncating control %s from %d\n",
|
||||||
|
@ -852,7 +878,8 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
|
||||||
coeff_blk.offset,
|
coeff_blk.offset,
|
||||||
coeff_blk.len,
|
coeff_blk.len,
|
||||||
coeff_blk.name,
|
coeff_blk.name,
|
||||||
coeff_blk.name_len);
|
coeff_blk.name_len,
|
||||||
|
coeff_blk.flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
adsp_err(dsp, "Failed to create control: %.*s, %d\n",
|
adsp_err(dsp, "Failed to create control: %.*s, %d\n",
|
||||||
coeff_blk.name_len, coeff_blk.name, ret);
|
coeff_blk.name_len, coeff_blk.name, ret);
|
||||||
|
@ -1237,7 +1264,7 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
|
||||||
len -= be32_to_cpu(adsp1_alg[i].dm);
|
len -= be32_to_cpu(adsp1_alg[i].dm);
|
||||||
len *= 4;
|
len *= 4;
|
||||||
wm_adsp_create_control(dsp, alg_region, 0,
|
wm_adsp_create_control(dsp, alg_region, 0,
|
||||||
len, NULL, 0);
|
len, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
|
adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
|
||||||
be32_to_cpu(adsp1_alg[i].alg.id));
|
be32_to_cpu(adsp1_alg[i].alg.id));
|
||||||
|
@ -1257,7 +1284,7 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
|
||||||
len -= be32_to_cpu(adsp1_alg[i].zm);
|
len -= be32_to_cpu(adsp1_alg[i].zm);
|
||||||
len *= 4;
|
len *= 4;
|
||||||
wm_adsp_create_control(dsp, alg_region, 0,
|
wm_adsp_create_control(dsp, alg_region, 0,
|
||||||
len, NULL, 0);
|
len, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
||||||
be32_to_cpu(adsp1_alg[i].alg.id));
|
be32_to_cpu(adsp1_alg[i].alg.id));
|
||||||
|
@ -1347,7 +1374,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
|
||||||
len -= be32_to_cpu(adsp2_alg[i].xm);
|
len -= be32_to_cpu(adsp2_alg[i].xm);
|
||||||
len *= 4;
|
len *= 4;
|
||||||
wm_adsp_create_control(dsp, alg_region, 0,
|
wm_adsp_create_control(dsp, alg_region, 0,
|
||||||
len, NULL, 0);
|
len, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
|
adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
|
||||||
be32_to_cpu(adsp2_alg[i].alg.id));
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
||||||
|
@ -1367,7 +1394,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
|
||||||
len -= be32_to_cpu(adsp2_alg[i].ym);
|
len -= be32_to_cpu(adsp2_alg[i].ym);
|
||||||
len *= 4;
|
len *= 4;
|
||||||
wm_adsp_create_control(dsp, alg_region, 0,
|
wm_adsp_create_control(dsp, alg_region, 0,
|
||||||
len, NULL, 0);
|
len, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
|
adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
|
||||||
be32_to_cpu(adsp2_alg[i].alg.id));
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
||||||
|
@ -1387,7 +1414,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
|
||||||
len -= be32_to_cpu(adsp2_alg[i].zm);
|
len -= be32_to_cpu(adsp2_alg[i].zm);
|
||||||
len *= 4;
|
len *= 4;
|
||||||
wm_adsp_create_control(dsp, alg_region, 0,
|
wm_adsp_create_control(dsp, alg_region, 0,
|
||||||
len, NULL, 0);
|
len, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
|
||||||
be32_to_cpu(adsp2_alg[i].alg.id));
|
be32_to_cpu(adsp2_alg[i].alg.id));
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
#define WMFW_MAX_COEFF_NAME 256
|
#define WMFW_MAX_COEFF_NAME 256
|
||||||
#define WMFW_MAX_COEFF_DESCR_NAME 256
|
#define WMFW_MAX_COEFF_DESCR_NAME 256
|
||||||
|
|
||||||
|
#define WMFW_CTL_FLAG_SYS 0x8000
|
||||||
|
#define WMFW_CTL_FLAG_VOLATILE 0x0004
|
||||||
|
#define WMFW_CTL_FLAG_WRITEABLE 0x0002
|
||||||
|
#define WMFW_CTL_FLAG_READABLE 0x0001
|
||||||
|
|
||||||
struct wmfw_header {
|
struct wmfw_header {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
__le32 len;
|
__le32 len;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue