diff --git a/src/audio/tone.c b/src/audio/tone.c index eee60914f060..f98e5e06e2c0 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -63,9 +63,8 @@ #define TONE_GAIN(v) Q_CONVERT_FLOAT(v, 31) /* Set default tone amplitude and frequency */ -#define TONE_AMPLITUDE_DEFAULT TONE_GAIN(0.5) /* -6 dB */ -#define TONE_FREQUENCY_DEFAULT TONE_FREQ(82.41) /* E2 note */ - +#define TONE_AMPLITUDE_DEFAULT TONE_GAIN(0.1) /* -20 dB */ +#define TONE_FREQUENCY_DEFAULT TONE_FREQ(997.0) #define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */ /* 2*pi/Fs lookup tables in Q1.31 for each Fs */ @@ -422,6 +421,8 @@ static struct comp_dev *tone_new(struct sof_ipc_comp *comp) comp_set_drvdata(dev, cd); cd->tone_func = tone_s32_default; + cd->rate = ipc_tone->sample_rate; + /* Reset tone generator and set channels volumes to default */ for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) tonegen_reset(&cd->sg[i]); @@ -448,17 +449,38 @@ static int tone_params(struct comp_dev *dev) trace_tone("par"); + /* Tone supports only S32_LE PCM format atm */ + if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) + return -EINVAL; + + trace_value(config->frame_fmt); + dev->params.frame_fmt = config->frame_fmt; + /* Need to compute this in non-host endpoint */ - dev->frame_bytes = - dev->params.sample_container_bytes * dev->params.channels; + dev->frame_bytes = comp_frame_bytes(dev); /* calculate period size based on config */ cd->period_bytes = dev->frames * dev->frame_bytes; - /* EQ supports only S32_LE PCM format */ - if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) - return -EINVAL; + return 0; +} +static int tone_cmd_get_value(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int j; + + trace_tone("mgt"); + + if (cdata->cmd == SOF_CTRL_CMD_SWITCH) { + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = !cd->sg[j].mute; + trace_value(j); + trace_value(cd->sg[j].mute); + } + } return 0; } @@ -480,6 +502,7 @@ static int tone_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cd trace_tone_error("che"); return -EINVAL; } + if (val) tonegen_unmute(&cd->sg[ch]); else @@ -583,6 +606,9 @@ static int tone_cmd(struct comp_dev *dev, int cmd, void *data) case COMP_CMD_SET_VALUE: ret = tone_cmd_set_value(dev, cdata); break; + case COMP_CMD_GET_VALUE: + ret = tone_cmd_get_value(dev, cdata); + break; } return ret; @@ -641,7 +667,6 @@ static int tone_prepare(struct comp_dev * dev) return ret; cd->channels = dev->params.channels; - cd->rate = dev->params.rate; tracev_value(cd->channels); tracev_value(cd->rate); diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 912926f69302..a5f46490a94a 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -715,6 +715,7 @@ struct sof_ipc_comp_mux { struct sof_ipc_comp_tone { struct sof_ipc_comp comp; struct sof_ipc_comp_config config; + int32_t sample_rate; int32_t frequency; int32_t amplitude; int32_t freq_mult; diff --git a/src/ipc/handler.c b/src/ipc/handler.c index a83ef6985786..9737141e8bb5 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -34,6 +34,7 @@ * */ +#include #include #include #include @@ -86,6 +87,71 @@ static inline struct sof_ipc_hdr *mailbox_validate(void) return hdr; } +/* check if a pipeline is hostless when walking downstream */ +static bool is_hostless_downstream(struct comp_dev *current) +{ + struct list_item *clist; + + /* check if current is a HOST comp */ + if (current->comp.type == SOF_COMP_HOST || + current->comp.type == SOF_COMP_SG_HOST) + return false; + + /* check if the pipeline has a HOST comp downstream */ + list_for_item(clist, ¤t->bsink_list) { + struct comp_buffer *buffer; + + buffer = container_of(clist, struct comp_buffer, source_list); + + /* don't go downstream if this component is not connected */ + if (!buffer->connected) + continue; + + /* dont go downstream if this comp belongs to another pipe */ + if (buffer->sink->comp.pipeline_id != current->comp.pipeline_id) + continue; + + /* return if there's a host comp downstream */ + if (!is_hostless_downstream(buffer->sink)) + return false; + } + + return true; +} + +/* check if a pipeline is hostless when walking upstream */ +static bool is_hostless_upstream(struct comp_dev *current) +{ + struct list_item *clist; + + /* check if current is a HOST comp */ + if (current->comp.type == SOF_COMP_HOST || + current->comp.type == SOF_COMP_SG_HOST) + return false; + + /* check if the pipeline has a HOST comp upstream */ + list_for_item(clist, ¤t->bsource_list) { + struct comp_buffer *buffer; + + buffer = container_of(clist, struct comp_buffer, sink_list); + + /* don't go upstream if this component is not connected */ + if (!buffer->connected) + continue; + + /* dont go upstream if this comp belongs to another pipeline */ + if (buffer->source->comp.pipeline_id != + current->comp.pipeline_id) + continue; + + /* return if there is a host comp upstream */ + if (!is_hostless_upstream(buffer->source)) + return false; + } + + return true; +} + /* * Stream IPC Operations. */ @@ -134,8 +200,14 @@ static int ipc_stream_pcm_params(uint32_t stream) cd = pcm_dev->cd; cd->params = pcm_params->params; -#ifdef CONFIG_HOST_PTABLE + /* + * walk in both directions to check if the pipeline is hostless + * skip page table set up if it is + */ + if (is_hostless_downstream(cd) && is_hostless_upstream(cd)) + goto pipe_params; +#ifdef CONFIG_HOST_PTABLE list_init(&elem_list); /* use DMA to read in compressed page table ringbuffer from host */ @@ -172,6 +244,8 @@ static int ipc_stream_pcm_params(uint32_t stream) } #endif +pipe_params: + /* configure pipeline audio params */ err = pipeline_params(pcm_dev->cd->pipeline, pcm_dev->cd, pcm_params); if (err < 0) {