aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/skylake/skl-topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/skylake/skl-topology.c')
-rw-r--r--sound/soc/intel/skylake/skl-topology.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 4624556f486d..5a4837dcfce3 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -54,12 +54,9 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w)
54 54
55/* 55/*
56 * Each pipelines needs memory to be allocated. Check if we have free memory 56 * Each pipelines needs memory to be allocated. Check if we have free memory
57 * from available pool. Then only add this to pool 57 * from available pool.
58 * This is freed when pipe is deleted
59 * Note: DSP does actual memory management we only keep track for complete
60 * pool
61 */ 58 */
62static bool skl_tplg_alloc_pipe_mem(struct skl *skl, 59static bool skl_is_pipe_mem_avail(struct skl *skl,
63 struct skl_module_cfg *mconfig) 60 struct skl_module_cfg *mconfig)
64{ 61{
65 struct skl_sst *ctx = skl->skl_sst; 62 struct skl_sst *ctx = skl->skl_sst;
@@ -74,10 +71,20 @@ static bool skl_tplg_alloc_pipe_mem(struct skl *skl,
74 "exceeds ppl memory available %d mem %d\n", 71 "exceeds ppl memory available %d mem %d\n",
75 skl->resource.max_mem, skl->resource.mem); 72 skl->resource.max_mem, skl->resource.mem);
76 return false; 73 return false;
74 } else {
75 return true;
77 } 76 }
77}
78 78
79/*
80 * Add the mem to the mem pool. This is freed when pipe is deleted.
81 * Note: DSP does actual memory management we only keep track for complete
82 * pool
83 */
84static void skl_tplg_alloc_pipe_mem(struct skl *skl,
85 struct skl_module_cfg *mconfig)
86{
79 skl->resource.mem += mconfig->pipe->memory_pages; 87 skl->resource.mem += mconfig->pipe->memory_pages;
80 return true;
81} 88}
82 89
83/* 90/*
@@ -85,10 +92,10 @@ static bool skl_tplg_alloc_pipe_mem(struct skl *skl,
85 * quantified in MCPS (Million Clocks Per Second) required for module/pipe 92 * quantified in MCPS (Million Clocks Per Second) required for module/pipe
86 * 93 *
87 * Each pipelines needs mcps to be allocated. Check if we have mcps for this 94 * Each pipelines needs mcps to be allocated. Check if we have mcps for this
88 * pipe. This adds the mcps to driver counter 95 * pipe.
89 * This is removed on pipeline delete
90 */ 96 */
91static bool skl_tplg_alloc_pipe_mcps(struct skl *skl, 97
98static bool skl_is_pipe_mcps_avail(struct skl *skl,
92 struct skl_module_cfg *mconfig) 99 struct skl_module_cfg *mconfig)
93{ 100{
94 struct skl_sst *ctx = skl->skl_sst; 101 struct skl_sst *ctx = skl->skl_sst;
@@ -98,13 +105,18 @@ static bool skl_tplg_alloc_pipe_mcps(struct skl *skl,
98 "%s: module_id %d instance %d\n", __func__, 105 "%s: module_id %d instance %d\n", __func__,
99 mconfig->id.module_id, mconfig->id.instance_id); 106 mconfig->id.module_id, mconfig->id.instance_id);
100 dev_err(ctx->dev, 107 dev_err(ctx->dev,
101 "exceeds ppl memory available %d > mem %d\n", 108 "exceeds ppl mcps available %d > mem %d\n",
102 skl->resource.max_mcps, skl->resource.mcps); 109 skl->resource.max_mcps, skl->resource.mcps);
103 return false; 110 return false;
111 } else {
112 return true;
104 } 113 }
114}
105 115
116static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
117 struct skl_module_cfg *mconfig)
118{
106 skl->resource.mcps += mconfig->mcps; 119 skl->resource.mcps += mconfig->mcps;
107 return true;
108} 120}
109 121
110/* 122/*
@@ -411,7 +423,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
411 mconfig = w->priv; 423 mconfig = w->priv;
412 424
413 /* check resource available */ 425 /* check resource available */
414 if (!skl_tplg_alloc_pipe_mcps(skl, mconfig)) 426 if (!skl_is_pipe_mcps_avail(skl, mconfig))
415 return -ENOMEM; 427 return -ENOMEM;
416 428
417 if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { 429 if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
@@ -435,6 +447,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
435 ret = skl_tplg_set_module_params(w, ctx); 447 ret = skl_tplg_set_module_params(w, ctx);
436 if (ret < 0) 448 if (ret < 0)
437 return ret; 449 return ret;
450 skl_tplg_alloc_pipe_mcps(skl, mconfig);
438 } 451 }
439 452
440 return 0; 453 return 0;
@@ -477,10 +490,10 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
477 struct skl_sst *ctx = skl->skl_sst; 490 struct skl_sst *ctx = skl->skl_sst;
478 491
479 /* check resource available */ 492 /* check resource available */
480 if (!skl_tplg_alloc_pipe_mcps(skl, mconfig)) 493 if (!skl_is_pipe_mcps_avail(skl, mconfig))
481 return -EBUSY; 494 return -EBUSY;
482 495
483 if (!skl_tplg_alloc_pipe_mem(skl, mconfig)) 496 if (!skl_is_pipe_mem_avail(skl, mconfig))
484 return -ENOMEM; 497 return -ENOMEM;
485 498
486 /* 499 /*
@@ -526,11 +539,15 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
526 src_module = dst_module; 539 src_module = dst_module;
527 } 540 }
528 541
542 skl_tplg_alloc_pipe_mem(skl, mconfig);
543 skl_tplg_alloc_pipe_mcps(skl, mconfig);
544
529 return 0; 545 return 0;
530} 546}
531 547
532static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 548static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
533 struct skl *skl, 549 struct skl *skl,
550 struct snd_soc_dapm_widget *src_w,
534 struct skl_module_cfg *src_mconfig) 551 struct skl_module_cfg *src_mconfig)
535{ 552{
536 struct snd_soc_dapm_path *p; 553 struct snd_soc_dapm_path *p;
@@ -547,6 +564,10 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
547 dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); 564 dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
548 565
549 next_sink = p->sink; 566 next_sink = p->sink;
567
568 if (!is_skl_dsp_widget_type(p->sink))
569 return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig);
570
550 /* 571 /*
551 * here we will check widgets in sink pipelines, so that 572 * here we will check widgets in sink pipelines, so that
552 * can be any widgets type and we are only interested if 573 * can be any widgets type and we are only interested if
@@ -576,7 +597,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
576 } 597 }
577 598
578 if (!sink) 599 if (!sink)
579 return skl_tplg_bind_sinks(next_sink, skl, src_mconfig); 600 return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig);
580 601
581 return 0; 602 return 0;
582} 603}
@@ -605,7 +626,7 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
605 * if sink is not started, start sink pipe first, then start 626 * if sink is not started, start sink pipe first, then start
606 * this pipe 627 * this pipe
607 */ 628 */
608 ret = skl_tplg_bind_sinks(w, skl, src_mconfig); 629 ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig);
609 if (ret) 630 if (ret)
610 return ret; 631 return ret;
611 632
@@ -773,10 +794,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
773 continue; 794 continue;
774 } 795 }
775 796
776 ret = skl_unbind_modules(ctx, src_module, dst_module); 797 skl_unbind_modules(ctx, src_module, dst_module);
777 if (ret < 0)
778 return ret;
779
780 src_module = dst_module; 798 src_module = dst_module;
781 } 799 }
782 800
@@ -814,9 +832,6 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
814 * This is a connecter and if path is found that means 832 * This is a connecter and if path is found that means
815 * unbind between source and sink has not happened yet 833 * unbind between source and sink has not happened yet
816 */ 834 */
817 ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
818 if (ret < 0)
819 return ret;
820 ret = skl_unbind_modules(ctx, src_mconfig, 835 ret = skl_unbind_modules(ctx, src_mconfig,
821 sink_mconfig); 836 sink_mconfig);
822 } 837 }
@@ -842,6 +857,12 @@ static int skl_tplg_vmixer_event(struct snd_soc_dapm_widget *w,
842 case SND_SOC_DAPM_PRE_PMU: 857 case SND_SOC_DAPM_PRE_PMU:
843 return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 858 return skl_tplg_mixer_dapm_pre_pmu_event(w, skl);
844 859
860 case SND_SOC_DAPM_POST_PMU:
861 return skl_tplg_mixer_dapm_post_pmu_event(w, skl);
862
863 case SND_SOC_DAPM_PRE_PMD:
864 return skl_tplg_mixer_dapm_pre_pmd_event(w, skl);
865
845 case SND_SOC_DAPM_POST_PMD: 866 case SND_SOC_DAPM_POST_PMD:
846 return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 867 return skl_tplg_mixer_dapm_post_pmd_event(w, skl);
847 } 868 }
@@ -916,6 +937,13 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
916 skl_get_module_params(skl->skl_sst, (u32 *)bc->params, 937 skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
917 bc->max, bc->param_id, mconfig); 938 bc->max, bc->param_id, mconfig);
918 939
940 /* decrement size for TLV header */
941 size -= 2 * sizeof(u32);
942
943 /* check size as we don't want to send kernel data */
944 if (size > bc->max)
945 size = bc->max;
946
919 if (bc->params) { 947 if (bc->params) {
920 if (copy_to_user(data, &bc->param_id, sizeof(u32))) 948 if (copy_to_user(data, &bc->param_id, sizeof(u32)))
921 return -EFAULT; 949 return -EFAULT;
@@ -950,7 +978,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
950 return -EFAULT; 978 return -EFAULT;
951 } else { 979 } else {
952 if (copy_from_user(ac->params, 980 if (copy_from_user(ac->params,
953 data + 2 * sizeof(u32), size)) 981 data + 2, size))
954 return -EFAULT; 982 return -EFAULT;
955 } 983 }
956 984
@@ -1510,6 +1538,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
1510 &skl_tplg_ops, fw, 0); 1538 &skl_tplg_ops, fw, 0);
1511 if (ret < 0) { 1539 if (ret < 0) {
1512 dev_err(bus->dev, "tplg component load failed%d\n", ret); 1540 dev_err(bus->dev, "tplg component load failed%d\n", ret);
1541 release_firmware(fw);
1513 return -EINVAL; 1542 return -EINVAL;
1514 } 1543 }
1515 1544