diff options
author | Jeeja KP <jeeja.kp@intel.com> | 2015-10-26 20:22:52 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-11-16 05:08:09 -0500 |
commit | 8724ff17521a91a87971027cf78631030091bc52 (patch) | |
tree | 21866f58048449874c033eff6f0899d7ac17884a /sound/soc/intel/skylake/skl-topology.c | |
parent | ce1b5551a06af31a72feeb50c02a9fe22599926a (diff) |
ASoC: Intel: Skylake: Add support for virtual dsp widgets
In SKL topology routes, some paths can be connected by a widget
which are not a DSP FW widget and virtual with respect to
firmware. In these case when module has to bind, then the
virtual DSP modules needs to skipped till a actual DSP module is
found which connects the pipelines.
So we need to walk the graph and find a widget which is real in
nature. This patch adds that support and splits
skl_tplg_pga_dapm_pre_pmu_event() fn with parsing code to
skl_tplg_bind_sinks() fn and call that recursively as well as
while parsing
The patch moves code a bit while splitting so diffstat doesn't
tell real picture
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/intel/skylake/skl-topology.c')
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.c | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index abbf8e7eb3e7..0c6e7833e652 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -397,40 +397,24 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
397 | return 0; | 397 | return 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | /* | 400 | static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, |
401 | * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA | 401 | struct skl *skl, |
402 | * we need to do following: | 402 | struct skl_module_cfg *src_mconfig) |
403 | * - Bind to sink pipeline | ||
404 | * Since the sink pipes can be running and we don't get mixer event on | ||
405 | * connect for already running mixer, we need to find the sink pipes | ||
406 | * here and bind to them. This way dynamic connect works. | ||
407 | * - Start sink pipeline, if not running | ||
408 | * - Then run current pipe | ||
409 | */ | ||
410 | static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | ||
411 | struct skl *skl) | ||
412 | { | 403 | { |
413 | struct snd_soc_dapm_path *p; | 404 | struct snd_soc_dapm_path *p; |
414 | struct snd_soc_dapm_widget *source, *sink; | 405 | struct snd_soc_dapm_widget *sink = NULL; |
415 | struct skl_module_cfg *src_mconfig, *sink_mconfig; | 406 | struct skl_module_cfg *sink_mconfig; |
416 | struct skl_sst *ctx = skl->skl_sst; | 407 | struct skl_sst *ctx = skl->skl_sst; |
417 | int ret = 0; | 408 | int ret; |
418 | |||
419 | source = w; | ||
420 | src_mconfig = source->priv; | ||
421 | 409 | ||
422 | /* | 410 | snd_soc_dapm_widget_for_each_sink_path(w, p) { |
423 | * find which sink it is connected to, bind with the sink, | ||
424 | * if sink is not started, start sink pipe first, then start | ||
425 | * this pipe | ||
426 | */ | ||
427 | snd_soc_dapm_widget_for_each_source_path(w, p) { | ||
428 | if (!p->connect) | 411 | if (!p->connect) |
429 | continue; | 412 | continue; |
430 | 413 | ||
431 | dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); | 414 | dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); |
432 | dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); | 415 | dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); |
433 | 416 | ||
417 | sink = p->sink; | ||
434 | /* | 418 | /* |
435 | * here we will check widgets in sink pipelines, so that | 419 | * here we will check widgets in sink pipelines, so that |
436 | * can be any widgets type and we are only interested if | 420 | * can be any widgets type and we are only interested if |
@@ -440,7 +424,6 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
440 | is_skl_dsp_widget_type(p->sink)) { | 424 | is_skl_dsp_widget_type(p->sink)) { |
441 | 425 | ||
442 | sink = p->sink; | 426 | sink = p->sink; |
443 | src_mconfig = source->priv; | ||
444 | sink_mconfig = sink->priv; | 427 | sink_mconfig = sink->priv; |
445 | 428 | ||
446 | /* Bind source to sink, mixin is always source */ | 429 | /* Bind source to sink, mixin is always source */ |
@@ -454,10 +437,43 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
454 | if (ret) | 437 | if (ret) |
455 | return ret; | 438 | return ret; |
456 | } | 439 | } |
457 | break; | ||
458 | } | 440 | } |
459 | } | 441 | } |
460 | 442 | ||
443 | if (!sink) | ||
444 | return skl_tplg_bind_sinks(sink, skl, src_mconfig); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA | ||
451 | * we need to do following: | ||
452 | * - Bind to sink pipeline | ||
453 | * Since the sink pipes can be running and we don't get mixer event on | ||
454 | * connect for already running mixer, we need to find the sink pipes | ||
455 | * here and bind to them. This way dynamic connect works. | ||
456 | * - Start sink pipeline, if not running | ||
457 | * - Then run current pipe | ||
458 | */ | ||
459 | static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | ||
460 | struct skl *skl) | ||
461 | { | ||
462 | struct skl_module_cfg *src_mconfig; | ||
463 | struct skl_sst *ctx = skl->skl_sst; | ||
464 | int ret = 0; | ||
465 | |||
466 | src_mconfig = w->priv; | ||
467 | |||
468 | /* | ||
469 | * find which sink it is connected to, bind with the sink, | ||
470 | * if sink is not started, start sink pipe first, then start | ||
471 | * this pipe | ||
472 | */ | ||
473 | ret = skl_tplg_bind_sinks(w, skl, src_mconfig); | ||
474 | if (ret) | ||
475 | return ret; | ||
476 | |||
461 | /* Start source pipe last after starting all sinks */ | 477 | /* Start source pipe last after starting all sinks */ |
462 | ret = skl_run_pipe(ctx, src_mconfig->pipe); | 478 | ret = skl_run_pipe(ctx, src_mconfig->pipe); |
463 | if (ret) | 479 | if (ret) |
@@ -466,6 +482,38 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
466 | return 0; | 482 | return 0; |
467 | } | 483 | } |
468 | 484 | ||
485 | static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( | ||
486 | struct snd_soc_dapm_widget *w, struct skl *skl) | ||
487 | { | ||
488 | struct snd_soc_dapm_path *p; | ||
489 | struct snd_soc_dapm_widget *src_w = NULL; | ||
490 | struct skl_sst *ctx = skl->skl_sst; | ||
491 | |||
492 | snd_soc_dapm_widget_for_each_source_path(w, p) { | ||
493 | src_w = p->source; | ||
494 | if (!p->connect) | ||
495 | continue; | ||
496 | |||
497 | dev_dbg(ctx->dev, "sink widget=%s\n", w->name); | ||
498 | dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); | ||
499 | |||
500 | /* | ||
501 | * here we will check widgets in sink pipelines, so that can | ||
502 | * be any widgets type and we are only interested if they are | ||
503 | * ones used for SKL so check that first | ||
504 | */ | ||
505 | if ((p->source->priv != NULL) && | ||
506 | is_skl_dsp_widget_type(p->source)) { | ||
507 | return p->source; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | if (src_w != NULL) | ||
512 | return skl_get_src_dsp_widget(src_w, skl); | ||
513 | |||
514 | return NULL; | ||
515 | } | ||
516 | |||
469 | /* | 517 | /* |
470 | * in the Post-PMU event of mixer we need to do following: | 518 | * in the Post-PMU event of mixer we need to do following: |
471 | * - Check if this pipe is running | 519 | * - Check if this pipe is running |
@@ -479,7 +527,6 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, | |||
479 | struct skl *skl) | 527 | struct skl *skl) |
480 | { | 528 | { |
481 | int ret = 0; | 529 | int ret = 0; |
482 | struct snd_soc_dapm_path *p; | ||
483 | struct snd_soc_dapm_widget *source, *sink; | 530 | struct snd_soc_dapm_widget *source, *sink; |
484 | struct skl_module_cfg *src_mconfig, *sink_mconfig; | 531 | struct skl_module_cfg *src_mconfig, *sink_mconfig; |
485 | struct skl_sst *ctx = skl->skl_sst; | 532 | struct skl_sst *ctx = skl->skl_sst; |
@@ -493,32 +540,18 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, | |||
493 | * one more sink before this sink got connected, Since source is | 540 | * one more sink before this sink got connected, Since source is |
494 | * started, bind this sink to source and start this pipe. | 541 | * started, bind this sink to source and start this pipe. |
495 | */ | 542 | */ |
496 | snd_soc_dapm_widget_for_each_sink_path(w, p) { | 543 | source = skl_get_src_dsp_widget(w, skl); |
497 | if (!p->connect) | 544 | if (source != NULL) { |
498 | continue; | 545 | src_mconfig = source->priv; |
499 | 546 | sink_mconfig = sink->priv; | |
500 | dev_dbg(ctx->dev, "sink widget=%s\n", w->name); | 547 | src_pipe_started = 1; |
501 | dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); | ||
502 | 548 | ||
503 | /* | 549 | /* |
504 | * here we will check widgets in sink pipelines, so that | 550 | * check pipe state, then no need to bind or start the |
505 | * can be any widgets type and we are only interested if | 551 | * pipe |
506 | * they are ones used for SKL so check that first | ||
507 | */ | 552 | */ |
508 | if ((p->source->priv != NULL) && | 553 | if (src_mconfig->pipe->state != SKL_PIPE_STARTED) |
509 | is_skl_dsp_widget_type(p->source)) { | 554 | src_pipe_started = 0; |
510 | source = p->source; | ||
511 | src_mconfig = source->priv; | ||
512 | sink_mconfig = sink->priv; | ||
513 | src_pipe_started = 1; | ||
514 | |||
515 | /* | ||
516 | * check pipe state, then no need to bind or start | ||
517 | * the pipe | ||
518 | */ | ||
519 | if (src_mconfig->pipe->state != SKL_PIPE_STARTED) | ||
520 | src_pipe_started = 0; | ||
521 | } | ||
522 | } | 555 | } |
523 | 556 | ||
524 | if (src_pipe_started) { | 557 | if (src_pipe_started) { |