X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sound%2Fsoc%2Fintel%2Fskylake%2Fskl-messages.c;h=826d4fd8930a5ca802f07bef5542bc26c199ffdf;hb=c9b1e834bc8decaf979344e8121e4ad1ded8dc8a;hp=c435a515b9b064270c85420e0fbf7585500bc32b;hpb=beb73b266a75602084361c5ef0baa5bc14637f4b;p=deliverable%2Flinux.git diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c435a515b9b0..826d4fd8930a 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -756,3 +756,129 @@ int skl_bind_modules(struct skl_sst *ctx, return ret; } + +static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, + enum skl_ipc_pipeline_state state) +{ + dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); + + return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); +} + +/* + * A pipeline is a collection of modules. Before a module in instantiated a + * pipeline needs to be created for it. + * This function creates pipeline, by sending create pipeline IPC messages + * to FW + */ +int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) +{ + int ret; + + dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); + + ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, + pipe->pipe_priority, pipe->ppl_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to create pipeline\n"); + return ret; + } + + pipe->state = SKL_PIPE_CREATED; + + return 0; +} + +/* + * A pipeline needs to be deleted on cleanup. If a pipeline is running, then + * pause the pipeline first and then delete it + * The pipe delete is done by sending delete pipeline IPC. DSP will stop the + * DMA engines and releases resources + */ +int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +{ + int ret; + + dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); + + /* If pipe is not started, do not try to stop the pipe in FW. */ + if (pipe->state > SKL_PIPE_STARTED) { + ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + if (ret < 0) { + dev_err(ctx->dev, "Failed to stop pipeline\n"); + return ret; + } + + pipe->state = SKL_PIPE_PAUSED; + } else { + /* If pipe was not created in FW, do not try to delete it */ + if (pipe->state < SKL_PIPE_CREATED) + return 0; + + ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); + if (ret < 0) + dev_err(ctx->dev, "Failed to delete pipeline\n"); + } + + return ret; +} + +/* + * A pipeline is also a scheduling entity in DSP which can be run, stopped + * For processing data the pipe need to be run by sending IPC set pipe state + * to DSP + */ +int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +{ + int ret; + + dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); + + /* If pipe was not created in FW, do not try to pause or delete */ + if (pipe->state < SKL_PIPE_CREATED) + return 0; + + /* Pipe has to be paused before it is started */ + ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + if (ret < 0) { + dev_err(ctx->dev, "Failed to pause pipe\n"); + return ret; + } + + pipe->state = SKL_PIPE_PAUSED; + + ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); + if (ret < 0) { + dev_err(ctx->dev, "Failed to start pipe\n"); + return ret; + } + + pipe->state = SKL_PIPE_STARTED; + + return 0; +} + +/* + * Stop the pipeline by sending set pipe state IPC + * DSP doesnt implement stop so we always send pause message + */ +int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) +{ + int ret; + + dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); + + /* If pipe was not created in FW, do not try to pause or delete */ + if (pipe->state < SKL_PIPE_PAUSED) + return 0; + + ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); + if (ret < 0) { + dev_dbg(ctx->dev, "Failed to stop pipe\n"); + return ret; + } + + pipe->state = SKL_PIPE_CREATED; + + return 0; +}