aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2015-04-20 08:52:45 -0400
committerMark Brown <broonie@kernel.org>2015-04-27 10:38:26 -0400
commit26c22a1922b9a5141f798e273e3e19b04a7a85de (patch)
tree1dfe99f2546f6ffa912935ca1d82d66b2b01ce11
parent8299ee8123a7ef708811c3ff09eae0cf0874b651 (diff)
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>
-rw-r--r--sound/soc/codecs/wm_adsp.c43
-rw-r--r--sound/soc/codecs/wmfw.h5
2 files changed, 40 insertions, 8 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 53fc7f88fa66..f6642c1c9ea4 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -240,6 +240,7 @@ struct wm_coeff_ctl {
240 size_t len; 240 size_t len;
241 unsigned int set:1; 241 unsigned int set:1;
242 struct snd_kcontrol *kcontrol; 242 struct snd_kcontrol *kcontrol;
243 unsigned int flags;
243}; 244};
244 245
245static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 246static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
@@ -472,7 +473,15 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
472 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 473 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
473 char *p = ucontrol->value.bytes.data; 474 char *p = ucontrol->value.bytes.data;
474 475
476 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
477 if (ctl->enabled)
478 return wm_coeff_read_control(ctl, p, ctl->len);
479 else
480 return -EPERM;
481 }
482
475 memcpy(p, ctl->cache, ctl->len); 483 memcpy(p, ctl->cache, ctl->len);
484
476 return 0; 485 return 0;
477} 486}
478 487
@@ -501,6 +510,15 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
501 kcontrol->put = wm_coeff_put; 510 kcontrol->put = wm_coeff_put;
502 kcontrol->private_value = (unsigned long)ctl; 511 kcontrol->private_value = (unsigned long)ctl;
503 512
513 if (ctl->flags) {
514 if (ctl->flags & WMFW_CTL_FLAG_WRITEABLE)
515 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
516 if (ctl->flags & WMFW_CTL_FLAG_READABLE)
517 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ;
518 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
519 kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
520 }
521
504 ret = snd_soc_add_card_controls(dsp->card, 522 ret = snd_soc_add_card_controls(dsp->card,
505 kcontrol, 1); 523 kcontrol, 1);
506 if (ret < 0) 524 if (ret < 0)
@@ -526,6 +544,9 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
526 list_for_each_entry(ctl, &dsp->ctl_list, list) { 544 list_for_each_entry(ctl, &dsp->ctl_list, list) {
527 if (!ctl->enabled || ctl->set) 545 if (!ctl->enabled || ctl->set)
528 continue; 546 continue;
547 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
548 continue;
549
529 ret = wm_coeff_read_control(ctl, 550 ret = wm_coeff_read_control(ctl,
530 ctl->cache, 551 ctl->cache,
531 ctl->len); 552 ctl->len);
@@ -544,7 +565,7 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
544 list_for_each_entry(ctl, &dsp->ctl_list, list) { 565 list_for_each_entry(ctl, &dsp->ctl_list, list) {
545 if (!ctl->enabled) 566 if (!ctl->enabled)
546 continue; 567 continue;
547 if (ctl->set) { 568 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
548 ret = wm_coeff_write_control(ctl, 569 ret = wm_coeff_write_control(ctl,
549 ctl->cache, 570 ctl->cache,
550 ctl->len); 571 ctl->len);
@@ -569,7 +590,8 @@ static void wm_adsp_ctl_work(struct work_struct *work)
569static int wm_adsp_create_control(struct wm_adsp *dsp, 590static int wm_adsp_create_control(struct wm_adsp *dsp,
570 const struct wm_adsp_alg_region *alg_region, 591 const struct wm_adsp_alg_region *alg_region,
571 unsigned int offset, unsigned int len, 592 unsigned int offset, unsigned int len,
572 const char *subname, unsigned int subname_len) 593 const char *subname, unsigned int subname_len,
594 unsigned int flags)
573{ 595{
574 struct wm_coeff_ctl *ctl; 596 struct wm_coeff_ctl *ctl;
575 struct wmfw_ctl_work *ctl_work; 597 struct wmfw_ctl_work *ctl_work;
@@ -577,6 +599,9 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
577 char *region_name; 599 char *region_name;
578 int ret; 600 int ret;
579 601
602 if (flags & WMFW_CTL_FLAG_SYS)
603 return 0;
604
580 switch (alg_region->type) { 605 switch (alg_region->type) {
581 case WMFW_ADSP1_PM: 606 case WMFW_ADSP1_PM:
582 region_name = "PM"; 607 region_name = "PM";
@@ -649,6 +674,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
649 ctl->ops.xput = wm_coeff_put; 674 ctl->ops.xput = wm_coeff_put;
650 ctl->dsp = dsp; 675 ctl->dsp = dsp;
651 676
677 ctl->flags = flags;
652 ctl->offset = offset; 678 ctl->offset = offset;
653 if (len > 512) { 679 if (len > 512) {
654 adsp_warn(dsp, "Truncating control %s from %d\n", 680 adsp_warn(dsp, "Truncating control %s from %d\n",
@@ -852,7 +878,8 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
852 coeff_blk.offset, 878 coeff_blk.offset,
853 coeff_blk.len, 879 coeff_blk.len,
854 coeff_blk.name, 880 coeff_blk.name,
855 coeff_blk.name_len); 881 coeff_blk.name_len,
882 coeff_blk.flags);
856 if (ret < 0) 883 if (ret < 0)
857 adsp_err(dsp, "Failed to create control: %.*s, %d\n", 884 adsp_err(dsp, "Failed to create control: %.*s, %d\n",
858 coeff_blk.name_len, coeff_blk.name, ret); 885 coeff_blk.name_len, coeff_blk.name, ret);
@@ -1237,7 +1264,7 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
1237 len -= be32_to_cpu(adsp1_alg[i].dm); 1264 len -= be32_to_cpu(adsp1_alg[i].dm);
1238 len *= 4; 1265 len *= 4;
1239 wm_adsp_create_control(dsp, alg_region, 0, 1266 wm_adsp_create_control(dsp, alg_region, 0,
1240 len, NULL, 0); 1267 len, NULL, 0, 0);
1241 } else { 1268 } else {
1242 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 1269 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1243 be32_to_cpu(adsp1_alg[i].alg.id)); 1270 be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1257,7 +1284,7 @@ static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
1257 len -= be32_to_cpu(adsp1_alg[i].zm); 1284 len -= be32_to_cpu(adsp1_alg[i].zm);
1258 len *= 4; 1285 len *= 4;
1259 wm_adsp_create_control(dsp, alg_region, 0, 1286 wm_adsp_create_control(dsp, alg_region, 0,
1260 len, NULL, 0); 1287 len, NULL, 0, 0);
1261 } else { 1288 } else {
1262 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1289 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1263 be32_to_cpu(adsp1_alg[i].alg.id)); 1290 be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1347,7 +1374,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1347 len -= be32_to_cpu(adsp2_alg[i].xm); 1374 len -= be32_to_cpu(adsp2_alg[i].xm);
1348 len *= 4; 1375 len *= 4;
1349 wm_adsp_create_control(dsp, alg_region, 0, 1376 wm_adsp_create_control(dsp, alg_region, 0,
1350 len, NULL, 0); 1377 len, NULL, 0, 0);
1351 } else { 1378 } else {
1352 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 1379 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1353 be32_to_cpu(adsp2_alg[i].alg.id)); 1380 be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1367,7 +1394,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1367 len -= be32_to_cpu(adsp2_alg[i].ym); 1394 len -= be32_to_cpu(adsp2_alg[i].ym);
1368 len *= 4; 1395 len *= 4;
1369 wm_adsp_create_control(dsp, alg_region, 0, 1396 wm_adsp_create_control(dsp, alg_region, 0,
1370 len, NULL, 0); 1397 len, NULL, 0, 0);
1371 } else { 1398 } else {
1372 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 1399 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1373 be32_to_cpu(adsp2_alg[i].alg.id)); 1400 be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1387,7 +1414,7 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1387 len -= be32_to_cpu(adsp2_alg[i].zm); 1414 len -= be32_to_cpu(adsp2_alg[i].zm);
1388 len *= 4; 1415 len *= 4;
1389 wm_adsp_create_control(dsp, alg_region, 0, 1416 wm_adsp_create_control(dsp, alg_region, 0,
1390 len, NULL, 0); 1417 len, NULL, 0, 0);
1391 } else { 1418 } else {
1392 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1419 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1393 be32_to_cpu(adsp2_alg[i].alg.id)); 1420 be32_to_cpu(adsp2_alg[i].alg.id));
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
index 04690b238b3c..7613d60d62ea 100644
--- a/sound/soc/codecs/wmfw.h
+++ b/sound/soc/codecs/wmfw.h
@@ -21,6 +21,11 @@
21#define WMFW_MAX_COEFF_NAME 256 21#define WMFW_MAX_COEFF_NAME 256
22#define WMFW_MAX_COEFF_DESCR_NAME 256 22#define WMFW_MAX_COEFF_DESCR_NAME 256
23 23
24#define WMFW_CTL_FLAG_SYS 0x8000
25#define WMFW_CTL_FLAG_VOLATILE 0x0004
26#define WMFW_CTL_FLAG_WRITEABLE 0x0002
27#define WMFW_CTL_FLAG_READABLE 0x0001
28
24struct wmfw_header { 29struct wmfw_header {
25 char magic[4]; 30 char magic[4];
26 __le32 len; 31 __le32 len;