/** This API is used to get output sample rate */ enum soc_result soc_audio_output_get_sample_rate(uint32_t processor_h, void *handle, int *sample_rate) { struct soc_audio_output_wl *output_wl; enum soc_result result = SOC_FAILURE; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Validate the arguments */ if (!handle || !sample_rate) { soc_debug_print(ERROR_LVL, "Invalid input handle"); result = SOC_ERROR_INVALID_PARAMETER; WARN_ON(1); goto EXIT; } output_wl = (struct soc_audio_output_wl *)handle; *sample_rate = output_wl->sample_rate; EXIT: SOC_EXIT(); return result; }
static enum soc_result audio_capture_pipe_enable_stages(struct soc_audio_pipeline *pipe_instance) { SOC_ENTER(); pipe_instance->stages[SOC_AUDIO_CAPTURE_INPUT_STAGE].task = SOC_AUDIO_PIPELINE_TASK_IN; pipe_instance->stages[SOC_AUDIO_CAPTURE_INPUT_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_CAPTURE_INPUT_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_CAPTURE_INPUT_STAGE].outputs_count = 1; #if 0 pipe_instance->stages[SOC_AUDIO_CAPTURE_SRC_STAGE].task = xxx; pipe_instance->stages[SOC_AUDIO_CAPTURE_SRC_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_CAPTURE_SRC_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_CAPTURE_SRC_STAGE].outputs_count = 1; #endif pipe_instance->stages[SOC_AUDIO_CAPTURE_OUTPUT_STAGE].task = SOC_AUDIO_PIPELINE_TASK_OUT; pipe_instance->stages[SOC_AUDIO_CAPTURE_OUTPUT_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_CAPTURE_OUTPUT_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_CAPTURE_OUTPUT_STAGE].outputs_count = 1; SOC_EXIT(); return SOC_SUCCESS; }
/** This function de-allocates all the resources for a pipeline. It should be called after the pipeline has been stopped. */ enum soc_result soc_audio_pipeline_delete(struct soc_audio_processor_context *ctx, struct soc_audio_pipeline **pipe_instance) { enum soc_result result = SOC_FAILURE; SOC_ENTER(); if (pipe_instance && *pipe_instance) { /*Proceed to deallocate stage buffers only if there is a output present. As the last output removal would have de-allocated all the buffers in pipe reconfigure.*/ if (0 != ctx->output_count) soc_bu_audio_pipe_disconnect(*pipe_instance); (*pipe_instance)->configured = false; /* Freeing memory context */ soc_audio_g_init_data.free_mem((*pipe_instance)->context); *pipe_instance = NULL; result = SOC_SUCCESS; } SOC_EXIT(); return result; }
/** This function calculates number of outputs needed for a pipeline */ void audio_pipeline_read_output_configs(struct soc_audio_processor_context *ctx, struct soc_audio_pipe_out *out_cfg) { struct soc_audio_output_wl *curr_output = NULL; uint32_t loop = 0; SOC_ENTER(); out_cfg->count = 0; out_cfg->ac3_encoded = false; out_cfg->dts_encoded = false; out_cfg->matrix_dec_enabled = false; curr_output = ctx->outputs; while (curr_output != NULL) { switch (curr_output->out_mode) { case SOC_AUDIO_OUTPUT_PCM: case SOC_AUDIO_OUTPUT_PASSTHROUGH: /* no action required */ break; case SOC_AUDIO_OUTPUT_ENCODED_DOLBY_DIGITAL: out_cfg->ac3_encoded = true; break; case SOC_AUDIO_OUTPUT_ENCODED_DTS: out_cfg->dts_encoded = true; break; case SOC_AUDIO_OUTPUT_INVALID: default: soc_debug_print(ERROR_LVL, "Invalid output mode\n"); break; } out_cfg->cfg[loop].output_handle = loop; out_cfg->cfg[loop].in_use = true; out_cfg->cfg[loop].ch_config = curr_output->channel_config; out_cfg->cfg[loop].sample_size = curr_output->sample_size; out_cfg->cfg[loop].sample_rate = curr_output->sample_rate; out_cfg->cfg[loop].channel_count = curr_output->channel_count; /*Get the dmix standard from the output*/ out_cfg->cfg[loop].out_mode = curr_output->out_mode; out_cfg->cfg[loop].dmix_mode = curr_output->dmix_mode; out_cfg->cfg[loop].ch_map = curr_output->ch_map; curr_output = curr_output->next_output; out_cfg->count++; loop++; } /*If we have no outputs,setup a default pipe so data will keep flowing*/ if (out_cfg->count == 0) { soc_debug_print(WARNING_LVL, "No output associated , adding one by default\n"); out_cfg->count = 1; } SOC_EXIT(); return; }
/* Remove output workload. * This function need processor lock protection, and caller need to make sure * the arguments are valid */ enum soc_result audio_output_remove(struct soc_audio_processor_context *ctx, struct soc_audio_output_wl *output_wl) { enum soc_result result = SOC_FAILURE; struct soc_audio_output_wl *rem_output = NULL; struct soc_audio_output_wl *prev_output = NULL; uint32_t ACE_sys_index = 0; SOC_ENTER(); /* Remove output from lint */ prev_output = rem_output = ctx->outputs; ACE_sys_index = 0; if (output_wl == ctx->outputs) { ctx->outputs = ctx->outputs->next_output; } else { /* traverse to find output, rem_output points to the * output to remove */ while (rem_output && (output_wl != rem_output)) { prev_output = rem_output; rem_output = rem_output->next_output; ACE_sys_index++; } /* remove output from list if a match found for * in_output_h */ if (rem_output) prev_output->next_output = rem_output->next_output; } /* free the memory if we find the output workload */ if (rem_output) { ctx->output_count--; #ifdef INCLUDE_QUALITY_STAGE result = audio_remove_ACE_system(ctx, ACE_sys_index); if (SOC_SUCCESS != result) { soc_debug_print(ERROR_LVL, "ACE System removal failed for ouput[%d]", ACE_sys_index); goto EXIT; } #endif kfree(rem_output); if (0 == ctx->output_count) ctx->outputs = NULL; result = SOC_SUCCESS; } else { /* output_h doesn't match any output ports */ result = SOC_ERROR_INVALID_PARAMETER; soc_debug_print(ERROR_LVL, "output_h doesn't match"); goto EXIT; } EXIT: SOC_EXIT(); return result; }
/** This function allocates resources needed for a pipeline and initializes it. */ struct soc_audio_pipeline *soc_audio_pipeline_add(uint32_t stages, uint32_t type) { struct soc_audio_pipeline *pipe_instance = NULL; uint32_t mem_size = 0, i = 0; void *context = NULL; SOC_ENTER(); if (stages < 1) { soc_debug_print(ERROR_LVL, "pipeline without any stages\n"); goto soc_pipeline_add_exit; } /* find the size of structure to be allocated soc_audio_pipeline structure already has one stage(to follow array notation) so allocate n-1 stage memory */ mem_size = sizeof(struct soc_audio_pipeline) + (sizeof(struct soc_audio_pipeline_stage) * (stages - 1)); soc_debug_print(DEBUG_LVL_2, "Memory requested %d\n", mem_size); /* we allocate the memory from bu specific memory allocater */ pipe_instance = (struct soc_audio_pipeline *) soc_audio_g_init_data.alloc_mem(mem_size, &context); if (pipe_instance == NULL) { soc_debug_print(ERROR_LVL, "Memory allocation failure for pipe.\n"); goto soc_pipeline_add_exit; } /* zero out initial allocation */ memset(pipe_instance, 0, mem_size); pipe_instance->started = false; pipe_instance->configured = false; /* Afix the bu specified pointer in pipeline, later we call the free with this pointer */ pipe_instance->context = context; pipe_instance->type = type; pipe_instance->num_stages = stages; /* Initialize all stages */ for (i = 0; i < stages; i++) { pipe_instance->stages[i].in_use = false; pipe_instance->stages[i].inputs_count = 0; pipe_instance->stages[i].outputs_count = 0; } soc_pipeline_add_exit: SOC_EXIT(); return pipe_instance; }
/** This API set the sample rate of the output_wl */ enum soc_result soc_audio_output_set_sample_rate(uint32_t processor_h, void *output_h, uint32_t sample_rate) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx = NULL; enum soc_result result = SOC_SUCCESS; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { /* Derive the output_wl */ output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; if ((sample_rate != output_wl->sample_rate) && (ctx->pipeline->configured)) output_wl->reconfig_post_proc_pipe = true; if ((output_wl->out_mode == SOC_AUDIO_OUTPUT_ENCODED_DOLBY_DIGITAL) && (sample_rate != 48000)) { result = SOC_ERROR_FEATURE_NOT_SUPPORTED; soc_debug_print(ERROR_LVL, "DD encoded output only supports 48kHz output!"); } else { output_wl->sample_rate = sample_rate; } } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return SOC_SUCCESS; }
/** This API is used to remove an output */ enum soc_result soc_audio_output_remove(uint32_t processor_h, void *output_h) { enum soc_result result = SOC_FAILURE; struct soc_audio_processor_context *ctx = NULL; struct soc_audio_output_wl *output_wl = NULL; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; /* Do the removal */ result = audio_output_remove(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; /*4 . Reconfigure the pipe *TODO : Validate this */ result = audio_post_proc_pipe_reconfig(ctx); if (SOC_SUCCESS != result) soc_debug_print(ERROR_LVL, "Reconfig pipe on output removal failed"); } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return result; }
/** This function sets up a post processing pipe 1. add required stages 2. connect the stages 3. configures the pipeline 4. starts the pipeline */ enum soc_result audio_post_proc_pipe_setup( struct soc_audio_processor_context *ctx) { struct soc_audio_pipeline *pipe_instance = ctx->pipeline; struct soc_audio_pipe_out out_cfg; enum soc_result result; SOC_ENTER(); memset(&out_cfg, 0, sizeof(struct soc_audio_pipe_out)); /* read all the output and consolidate it at one place */ audio_pipeline_read_output_configs(ctx, &out_cfg); pipe_instance->op_type = PIPE_OPS_PLAYBACK; /* Add Required Stages*/ result = audio_post_proc_pipe_set_post_mix_stages(&out_cfg, pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "post_proc_pipe_enable_stages failed result = %d\n", result); return result; } /* Connect the Stages*/ result = soc_bu_audio_pipe_update_connect(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "BU specific function to connect stages failed\n"); return result; } /* Configure the pipeleine */ result = soc_ipc_config_pipe(ctx, pipe_instance); if (result != SOC_SUCCESS) { soc_audio_pipeline_delete(ctx, &pipe_instance); soc_debug_print(ERROR_LVL, "IPC sending to BU specific function to connect " "stages failed\n"); return result; } pipe_instance->configured = true; SOC_EXIT(); return SOC_SUCCESS; }
/** This API is used to disable the output */ enum soc_result soc_audio_output_disable(uint32_t processor_h, void *output_h) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx; enum soc_result result; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { /* Derive the output_wl */ output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; /* Check if the output is not already disabled */ if (false == output_wl->enabled) { soc_debug_print(DEBUG_LVL_2, "Output Disable : Already disabled"); result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; } output_wl->enabled = false; } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return SOC_SUCCESS; }
/** This API is used to enable an output */ enum soc_result soc_audio_output_enable(uint32_t processor_h, void *output_h) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx = NULL; enum soc_result result = SOC_SUCCESS; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; /* Set the enable flag in the output_wl */ output_wl->enabled = true; /*If the reconfig flag in output_wl is true * Reconfigure the pipeline */ if (true == output_wl->reconfig_post_proc_pipe) result = audio_post_proc_pipe_reconfig(ctx); if (result == SOC_SUCCESS) output_wl->reconfig_post_proc_pipe = false; } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return result; }
/** This API set the channel config ofthe output */ enum soc_result soc_audio_output_set_channel_config(uint32_t processor_h, void *output_h, enum soc_audio_channel_config ch_config) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx = NULL; enum soc_result result = SOC_SUCCESS; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { /* Derive the output_wl */ output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; if ((ch_config != output_wl->channel_config) && (ctx->pipeline->configured)) output_wl->reconfig_post_proc_pipe = true; output_wl->channel_config = ch_config; } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return SOC_SUCCESS; }
/** This function adds the basic stages needed in a pipeline */ static enum soc_result audio_dec_pipe_enable_stages(struct soc_audio_pipeline *pipe_instance) { SOC_ENTER(); #ifdef INCLUDE_INPUT_STAGE pipe_instance->stages[SOC_AUDIO_DEC_INPUT_STAGE].task = SOC_AUDIO_PIPELINE_TASK_IN; pipe_instance->stages[SOC_AUDIO_DEC_INPUT_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_DEC_INPUT_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_DEC_INPUT_STAGE].outputs_count = 1; #endif /* INCLUDE_INPUT_STAGE */ #ifdef INCLUDE_DECODE_STAGE pipe_instance->stages[SOC_AUDIO_DEC_DECODE_STAGE].task = SOC_AUDIO_PIPELINE_TASK_DECODE; pipe_instance->stages[SOC_AUDIO_DEC_DECODE_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_DEC_DECODE_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_DEC_DECODE_STAGE].outputs_count = 1; #endif /* INCLUDE DECODE STAGE */ #ifdef INCLUDE_PRESRC_STAGE pipe_instance->stages[SOC_AUDIO_DEC_PRESRC_STAGE].task = SOC_AUDIO_PIPELINE_TASK_PRESRC; pipe_instance->stages[SOC_AUDIO_DEC_PRESRC_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_DEC_PRESRC_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_DEC_PRESRC_STAGE].outputs_count = 1; #endif /* INCLUDE PRESRC STAGE */ #ifdef INCLUDE_OUTPUT_STAGE pipe_instance->stages[SOC_AUDIO_DEC_OUTPUT_STAGE].task = SOC_AUDIO_PIPELINE_TASK_OUT; pipe_instance->stages[SOC_AUDIO_DEC_OUTPUT_STAGE].in_use = true; pipe_instance->stages[SOC_AUDIO_DEC_OUTPUT_STAGE].inputs_count = 1; pipe_instance->stages[SOC_AUDIO_DEC_OUTPUT_STAGE].outputs_count = 1; #endif /* INCLUDE_OUTPUT_STAGE */ SOC_EXIT(); return SOC_SUCCESS; }
/** This API is used to add an output */ enum soc_result soc_audio_output_add(uint32_t processor_h, struct soc_audio_output_config config, void **output_h) { enum soc_result result = SOC_FAILURE; struct soc_audio_processor_context *ctx = NULL; struct soc_audio_output_wl *new_output = NULL, *curr_output = NULL, *prev_output = NULL; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { if (ctx->ref_count == 0) { soc_debug_print(ERROR_LVL, "Invalid args"); result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; } /* Allocate and initialize new output port */ new_output = (struct soc_audio_output_wl *) kmalloc(sizeof(struct soc_audio_output_wl), GFP_KERNEL); if (NULL == new_output) { soc_debug_print(ERROR_LVL, "Out of memory"); result = SOC_ERROR_NO_RESOURCES; goto EXIT_UNLOCK; } /* Initialize the output wl with the config passed in */ memset(new_output, 0, sizeof(struct soc_audio_output_wl)); new_output->ctx = ctx; new_output->sample_rate = config.sample_rate; new_output->sample_size = config.sample_size; new_output->channel_config = config.ch_config; new_output->ch_map = config.ch_map; new_output->out_mode = config.out_mode; new_output->channel_count = audio_output_ch_config_to_count(new_output->channel_config); /* Set defaults */ new_output->dmix_mode = SOC_AUDIO_DOWNMIX_INVALID; /* Set the reconfigure flag true */ if (ctx->pipeline->configured) new_output->reconfig_post_proc_pipe = true; /* Add newly created output to ctx */ ctx->output_count++; prev_output = curr_output = ctx->outputs; if (NULL == curr_output) { ctx->outputs = new_output; } else { /* traverse to end of list */ while (curr_output) { prev_output = curr_output; curr_output = curr_output->next_output; } prev_output->next_output = new_output; } #ifdef INCLUDE_QUALITY_STAGE /* Add a ACE system for the new output */ result = audio_add_ACE_system(ctx); if (SOC_SUCCESS != result) { soc_debug_print(ERROR_LVL, "ACE System alloc failed for ouput[%d]\n", ctx->output_count); goto EXIT_UNLOCK; } #endif /* Return handle to user */ *output_h = (void *)new_output; result = SOC_SUCCESS; } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return result; }
/** This function adds the basic stages needed in a pipeline */ enum soc_result audio_post_proc_pipe_set_post_mix_stages(const struct soc_audio_pipe_out *output_cfg, struct soc_audio_pipeline *pipe_instance) { enum soc_result result = SOC_FAILURE; SOC_ENTER(); #ifdef INCLUDE_DOWNMIXER_STAGE /* Downmix stage */ pipe_instance->stages[SOC_AUDIO_DOWNMIX_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_DOWNMIX_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_DOWNMIXER_STAGE */ #ifdef INCLUDE_POSTSRC_STAGE /* Post SRC stage */ pipe_instance->stages[SOC_AUDIO_POST_SRC_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_POST_SRC_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_POSTSRC_STAGE */ #ifdef INCLUDE_QUALITY_STAGE /* Audio Quality stage */ pipe_instance->stages[SOC_AUDIO_QUALITY_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_QUALITY_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_QUALITY_STAGE */ #ifdef INCLUDE_INTERLEAVER_STAGE /* Need to preform an interleave */ pipe_instance->stages[SOC_AUDIO_INTERLVR_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_INTERLVR_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_INTERLEAVER_STAGE */ #ifdef INCLUDE_PER_OUTPUT_DELAY_STAGE /* per output delay stage */ pipe_instance->stages[SOC_AUDIO_PER_OUTPUT_DELAY_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_PER_OUTPUT_DELAY_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_PER_OUTPUT_DELAY_STAGE */ #ifdef INCLUDE_OUTPUT_STAGE pipe_instance->stages[SOC_AUDIO_OUTPUT_STAGE].inputs_count = output_cfg->count; pipe_instance->stages[SOC_AUDIO_OUTPUT_STAGE].outputs_count = output_cfg->count; #endif /* INCLUDE_OUTPUT_STAGE */ /* Do BU specific parameter settings for each stage */ result = soc_bu_audio_post_proc_pipe_init_stages(pipe_instance, output_cfg); SOC_EXIT(); return result; }
/* Use to specify a specific downmix to be transmitted via an output. */ enum soc_result soc_audio_output_set_downmix_mode(uint32_t processor_h, void *output_h, enum soc_audio_downmix_mode dmix_mode) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx = NULL; enum soc_result result = SOC_SUCCESS; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) { result = SOC_ERROR_INVALID_PARAMETER; goto EXIT; } /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { /* Derive the output_wl and processor handle */ output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) { result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; } /* Check if the output is not already enabled */ if (true == output_wl->enabled) { soc_debug_print(ERROR_LVL, "Output is enabled," "please disable before trying to set downmix mode"); result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; } switch (dmix_mode) { case SOC_AUDIO_DOWNMIX_DEFAULT: case SOC_AUDIO_DOWNMIX_1_0: case SOC_AUDIO_DOWNMIX_1_0_LFE: case SOC_AUDIO_DOWNMIX_2_0: case SOC_AUDIO_DOWNMIX_2_0_NO_SCALE: case SOC_AUDIO_DOWNMIX_2_0_LFE: case SOC_AUDIO_DOWNMIX_2_1: case SOC_AUDIO_DOWNMIX_2_1_LFE: case SOC_AUDIO_DOWNMIX_2_0_LTRT: case SOC_AUDIO_DOWNMIX_2_0_LTRT_NO_SCALE: case SOC_AUDIO_DOWNMIX_2_0_DOLBY_PRO_LOGIC_II: case SOC_AUDIO_DOWNMIX_2_0_DOLBY_PRO_LOGIC_II_NO_SCALE: case SOC_AUDIO_DOWNMIX_2_0_DVB_AAC: case SOC_AUDIO_DOWNMIX_3_0: case SOC_AUDIO_DOWNMIX_3_0_LFE: case SOC_AUDIO_DOWNMIX_3_1: case SOC_AUDIO_DOWNMIX_3_1_LFE: case SOC_AUDIO_DOWNMIX_2_2: case SOC_AUDIO_DOWNMIX_2_2_LFE: case SOC_AUDIO_DOWNMIX_3_2: case SOC_AUDIO_DOWNMIX_3_2_LFE: case SOC_AUDIO_DOWNMIX_3_0_1: case SOC_AUDIO_DOWNMIX_3_0_1_LFE: case SOC_AUDIO_DOWNMIX_2_2_1: case SOC_AUDIO_DOWNMIX_2_2_1_LFE: case SOC_AUDIO_DOWNMIX_3_2_1: case SOC_AUDIO_DOWNMIX_3_2_1_LFE: case SOC_AUDIO_DOWNMIX_3_0_2: case SOC_AUDIO_DOWNMIX_3_0_2_LFE: case SOC_AUDIO_DOWNMIX_2_2_2: case SOC_AUDIO_DOWNMIX_2_2_2_LFE: case SOC_AUDIO_DOWNMIX_3_2_2: case SOC_AUDIO_DOWNMIX_3_2_2_LFE: output_wl->dmix_mode = dmix_mode; break; case SOC_AUDIO_DOWNMIX_INVALID: default: result = SOC_ERROR_INVALID_PARAMETER; break; } } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return result; }
enum soc_result soc_audio_output_set_mode(uint32_t processor_h, void *output_h, enum soc_audio_output_mode mode) { struct soc_audio_output_wl *output_wl; struct soc_audio_processor_context *ctx = NULL; enum soc_result result = SOC_SUCCESS; SOC_ENTER(); /* Validate processor handle */ result = audio_processor_handle_validation(processor_h); if (SOC_SUCCESS != result) goto EXIT; /* Derive the processor context */ ctx = &soc_audio_processor[processor_h]; mutex_lock(&ctx->processor_lock); { /* Derive the output_wl and processor handle */ output_wl = (struct soc_audio_output_wl *)output_h; /* Validate output workload */ result = audio_output_workload_validation(ctx, output_wl); if (SOC_SUCCESS != result) goto EXIT_UNLOCK; /* Check if the output is not already enabled */ if (true == output_wl->enabled) { soc_debug_print(ERROR_LVL, "Output set mode : Cannot change mode " "of enabled output"); result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; } /* If the mode is the same, do nothing */ if (output_wl->out_mode != mode) { result = SOC_SUCCESS; goto EXIT_UNLOCK; } /*First figure out what the previous mode was and clean up */ switch (output_wl->out_mode) { case SOC_AUDIO_OUTPUT_PCM: break; case SOC_AUDIO_OUTPUT_PASSTHROUGH: /*TODO For passthrough implementation add a flag passthrough*/ break; case SOC_AUDIO_OUTPUT_ENCODED_DOLBY_DIGITAL: case SOC_AUDIO_OUTPUT_ENCODED_DTS: /*TODO render related flags not present in soc_audio_output_wl*/ break; case SOC_AUDIO_OUTPUT_INVALID: default: result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; break; } /*Now reconfigure the output with the new mode */ switch (mode) { case SOC_AUDIO_OUTPUT_PCM: /*TODO render related flags not present in soc_audio_output_wl*/ break; case SOC_AUDIO_OUTPUT_PASSTHROUGH: /*TODO For passthrough implementation add a flag passthrough */ break; case SOC_AUDIO_OUTPUT_ENCODED_DOLBY_DIGITAL: /*TODO render related flags not present in soc_audio_output_wl*/ break; case SOC_AUDIO_OUTPUT_ENCODED_DTS: /*TODO render related flags not present in soc_audio_output_wl*/ break; case SOC_AUDIO_OUTPUT_INVALID: default: result = SOC_ERROR_INVALID_PARAMETER; goto EXIT_UNLOCK; break; } /* Finally setup the output mode */ output_wl->out_mode = mode; } EXIT_UNLOCK: mutex_unlock(&ctx->processor_lock); EXIT: SOC_EXIT(); return SOC_SUCCESS; }
/** This function sets up a decode pipe 1. allocate the pipe 2. add required stages 3. connect the stages 4. configures the pipeline */ enum soc_result audio_dec_pipe_setup(struct soc_audio_input_wl *input_wl) { struct soc_audio_processor_context *ctx = NULL; struct soc_audio_pipeline *pipe_instance; enum soc_result result; SOC_ENTER(); /* Get processor context */ ctx = input_wl->ctx; pipe_instance = input_wl->pipeline = soc_audio_pipeline_add(SOC_AUDIO_DEC_STAGE_COUNT, SOC_AUDIO_DEC_PIPE); if (pipe_instance == NULL) { soc_debug_print(ERROR_LVL, "pipeline creation failed for decode\n"); return SOC_ERROR_NO_RESOURCES; } pipe_instance->op_type = PIPE_OPS_PLAYBACK; /* Allocate decode pipe */ result = soc_ipc_alloc_pipe(ctx, pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "pipeline addition failed\n"); return result; } /* Set default decoder param */ result = audio_pipe_set_default_decoder_param(input_wl); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "set_default_decoder_param failed\n"); return result; } /* Add decode stages */ result = audio_dec_pipe_enable_stages(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "pipeline_add_dec_stage failed with result = %d\n", result); return result; } /* Decode BU specific stage initializations */ result = soc_bu_audio_dec_pipe_init_stages(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "soc_bu_audio_dec_pipe_init_stages failed result = %d\n", result); return result; } /* Connect decode stages */ result = soc_bu_audio_pipe_update_connect(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "BU pipe connect failed\n"); return result; } SOC_EXIT(); return result; }
/* This is used to set default decoder paramaters */ static enum soc_result audio_pipe_set_default_decoder_param(struct soc_audio_input_wl *input_wl) { enum soc_result result = SOC_FAILURE; #if defined(INCLUDE_DECODE_STAGE) || defined(INCLUDE_ENCODE_STAGE) enum soc_audio_format format; struct soc_audio_codec_params *params; SOC_ENTER(); /* Get the params from decode stage parameters */ params = &input_wl->pipeline->stages[SOC_AUDIO_DEC_DECODE_STAGE]. stage_params.decoder.host; /* If DTS core is in the input stream, but only DTSHD decoder, * need to force format to DTSHD since we will use the DTSHD * decoder. */ if (input_wl->format == SOC_AUDIO_MEDIA_FMT_DTS) format = SOC_AUDIO_MEDIA_FMT_DTS_HD; else format = input_wl->format; /* Call the format specific setup function to setup stage parameters */ switch (format) { case SOC_AUDIO_MEDIA_FMT_PCM: case SOC_AUDIO_MEDIA_FMT_DVD_PCM: case SOC_AUDIO_MEDIA_FMT_BLURAY_PCM: result = SOC_ERROR_INVALID_PARAMETER; soc_debug_print(ERROR_LVL, "Codec parameters not set, format is PCM!"); break; case SOC_AUDIO_MEDIA_FMT_DD: #ifdef INCLUDE_AC3_DECODE audio_ac3_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_DD_PLUS: #ifdef INCLUDE_DDPLUS_DECODE audio_ddplus_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_DTS: #ifdef INCLUDE_DTS_DECODE audio_dts_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_DTS_LBR: #ifdef INCLUDE_DTS_LBR_DECODE audio_dts_lbr_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_DTS_BC: result = SOC_ERROR_FEATURE_NOT_SUPPORTED; break; case SOC_AUDIO_MEDIA_FMT_MPEG: #ifdef INCLUDE_MPEG_DECODE audio_mpeg_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_WM9: result = SOC_ERROR_FEATURE_NOT_SUPPORTED; break; case SOC_AUDIO_MEDIA_FMT_TRUE_HD: #ifdef INCLUDE_TRUEHD_DECODE audio_truehd_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_DTS_HD: case SOC_AUDIO_MEDIA_FMT_DTS_HD_HRA: case SOC_AUDIO_MEDIA_FMT_DTS_HD_MA: #ifdef INCLUDE_DTS_HD_DECODE audio_dts_hd_set_default_dec_params(params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_AAC: case SOC_AUDIO_MEDIA_FMT_AAC_LOAS: #ifdef INCLUDE_AAC_DECODE audio_aac_set_default_dec_params(format, params); result = SOC_SUCCESS; #else result = SOC_ERROR_FEATURE_NOT_SUPPORTED; #endif break; case SOC_AUDIO_MEDIA_FMT_COUNT: case SOC_AUDIO_MEDIA_FMT_INVALID: default: result = SOC_ERROR_INVALID_PARAMETER; soc_debug_print(ERROR_LVL, "No decoder is setup on the input!"); break; } /* Call the BU function to set up BU specific parameters */ if (SOC_SUCCESS == result) { result = soc_bu_audio_pipe_set_default_decoder_param(format, params); if (SOC_SUCCESS != result) { soc_debug_print(ERROR_LVL, "bu set default decodeer " "param failed"); } } else if (SOC_ERROR_FEATURE_NOT_SUPPORTED == result) { soc_debug_print(ERROR_LVL, "Format %d not supported", format); } else { soc_debug_print(ERROR_LVL, "Can not write codec parameter to pipeline"); } SOC_EXIT(); return result; #else return result; #endif }
enum soc_result audio_capture_pipe_setup(struct soc_audio_input_wl *input_wl) { enum soc_result result = SOC_SUCCESS; struct soc_audio_processor_context *ctx = NULL; struct soc_audio_pipeline *pipe_instance = NULL; SOC_ENTER(); /* Get processor context */ ctx = input_wl->ctx; pipe_instance = input_wl->pipeline = soc_audio_pipeline_add(SOC_AUDIO_CAPTURE_STAGE_COUNT, SOC_AUDIO_CPR_PIPE); if (pipe_instance == NULL) { soc_debug_print(ERROR_LVL, "pipeline creation failed for capture\n"); result = SOC_ERROR_NO_RESOURCES; goto audio_capture_pipe_setup_exit; } pipe_instance->op_type = PIPE_OPS_CAPTURE; /* Allocate capture pipe */ result = soc_ipc_alloc_pipe(ctx, pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "pipeline addition failed\n"); goto audio_capture_pipe_setup_exit; } /* Add capture stages */ result = audio_capture_pipe_enable_stages(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "pipeline_add_capture_stage failed result = %d\n", result); goto audio_capture_pipe_setup_exit; } /* Capture BU specific stage initializations */ result = soc_bu_audio_capture_pipe_init_stages(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "soc_bu_audio_capture_pipe_init_stages failed result = %d\n", result); goto audio_capture_pipe_setup_exit; } /* Connect capture stages */ result = soc_bu_audio_pipe_update_connect(pipe_instance); if (result != SOC_SUCCESS) { soc_debug_print(ERROR_LVL, "BU pipe connect failed\n"); goto audio_capture_pipe_setup_exit; } /* Configure pipeline */ result = soc_ipc_config_pipe(ctx, pipe_instance); if (result != SOC_SUCCESS) { soc_audio_pipeline_delete(ctx, &pipe_instance); soc_debug_print(ERROR_LVL, "Capture pipe config failed\n"); goto audio_capture_pipe_setup_exit; } pipe_instance->configured = true; audio_capture_pipe_setup_exit: SOC_EXIT(); return result; }