示例#1
0
/**
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;
}
示例#2
0
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;
}
示例#3
0
/**
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;
}
示例#4
0
/**
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;
}
示例#5
0
/* 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;
}
示例#6
0
/**
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;
}
示例#7
0
/**
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;
}
示例#8
0
/**
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;
}
示例#9
0
/**
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;
}
示例#10
0
/**
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;
}
示例#11
0
/**
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;

}
示例#12
0
/**
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;

}
示例#13
0
/**
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;
}
示例#14
0
/**
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;
}
示例#15
0
/**
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;
}
示例#16
0
/* 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;
}
示例#17
0
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;
}
示例#18
0
/**
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;
}
示例#19
0
/*
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
}
示例#20
0
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;
}