diff options
| -rw-r--r-- | sound/soc/codecs/wm_adsp.c | 43 | ||||
| -rw-r--r-- | sound/soc/codecs/wmfw.h | 5 |
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 | ||
| 245 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 246 | static 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) | |||
| 569 | static int wm_adsp_create_control(struct wm_adsp *dsp, | 590 | static 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 | |||
| 24 | struct wmfw_header { | 29 | struct wmfw_header { |
| 25 | char magic[4]; | 30 | char magic[4]; |
| 26 | __le32 len; | 31 | __le32 len; |
