diff --git a/src/audio/volume/volume.c b/src/audio/volume/volume.c index 080c4a3a9ae1..2f78d8781ff1 100644 --- a/src/audio/volume/volume.c +++ b/src/audio/volume/volume.c @@ -39,35 +39,33 @@ #include #include +/* Shift to use in volume fractional multiplications */ +#define Q_MUL_SHIFT Q_SHIFT_BITS_32(VOL_QXY_Y, VOL_QXY_Y, VOL_QXY_Y) + /** * \brief Synchronize host mmap() volume with real value. * \param[in,out] cd Volume component private data. - * \param[in] chan Channel number. + * \param[in] num_channels Update channels 0 to num_channels -1. */ -static void vol_sync_host(struct comp_data *cd, uint32_t chan) +static void vol_sync_host(struct comp_data *cd, unsigned int num_channels) { - if (!cd->hvol) + int n; + + if (!cd->hvol) { + tracev_volume("vol_sync_host() Warning: null hvol, no update"); return; + } - if (chan < SOF_IPC_MAX_CHANNELS) { - cd->hvol[chan].value = cd->volume[chan]; + if (num_channels < SOF_IPC_MAX_CHANNELS) { + for (n = 0; n < num_channels; n++) + cd->hvol[n].value = cd->volume[n]; } else { - trace_volume_error("vol_sync_host() error: " - "chan = %u < SOF_IPC_MAX_CHANNELS", chan); + trace_volume_error("vol_sync_host() error: channels count %d" + " exceeds SOF_IPC_MAX_CHANNELS", + num_channels); } } -/** - * \brief Update volume with target value. - * \param[in,out] cd Volume component private data. - * \param[in] chan Channel number. - */ -static void vol_update(struct comp_data *cd, uint32_t chan) -{ - cd->volume[chan] = cd->tvolume[chan]; - vol_sync_host(cd, chan); -} - /** * \brief Ramps volume changes over time. * \param[in,out] data Volume base component device. @@ -82,10 +80,24 @@ static enum task_state vol_work(void *data) int again = 0; int i; + /* No need to ramp in idle state, jump volume to request. */ + if (dev->state == COMP_STATE_READY) { + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + cd->volume[i] = cd->tvolume[i]; + + vol_sync_host(cd, PLATFORM_MAX_CHANNELS); + return SOF_TASK_STATE_COMPLETED; + } + + /* The first is set and cleared to indicate ongoing ramp, the + * latter is set once to enable self launched ramp only once + * in stream start. + */ cd->vol_ramp_active = true; + cd->ramp_started = true; - /* inc/dec each volume if it's not at target */ - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { + /* inc/dec each volume if it's not at target for active channels */ + for (i = 0; i < cd->channels; i++) { /* skip if target reached */ if (cd->volume[i] == cd->tvolume[i]) continue; @@ -98,8 +110,8 @@ static enum task_state vol_work(void *data) if (cd->volume[i] < cd->tvolume[i]) { /* ramp up, check if ramp completed */ if (vol >= cd->tvolume[i] || vol >= cd->vol_max) { - vol_update(cd, i); cd->ramp_increment[i] = 0; + cd->volume[i] = cd->tvolume[i]; } else { cd->volume[i] = vol; again = 1; @@ -108,14 +120,14 @@ static enum task_state vol_work(void *data) /* ramp down */ if (vol <= 0) { /* cannot ramp down below 0 */ - vol_update(cd, i); cd->ramp_increment[i] = 0; + cd->volume[i] = cd->tvolume[i]; } else { /* ramp completed ? */ if (vol <= cd->tvolume[i] || vol <= cd->vol_min) { - vol_update(cd, i); cd->ramp_increment[i] = 0; + cd->volume[i] = cd->tvolume[i]; } else { cd->volume[i] = vol; again = 1; @@ -123,10 +135,11 @@ static enum task_state vol_work(void *data) } } - /* sync host with new value */ - vol_sync_host(cd, i); } + /* sync host with new value */ + vol_sync_host(cd, cd->channels); + /* do we need to continue ramping */ if (again) return SOF_TASK_STATE_RESCHEDULE; @@ -228,6 +241,8 @@ static struct comp_dev *volume_new(struct sof_ipc_comp *comp) } cd->vol_ramp_active = false; + cd->channels = 0; /* To be set in prepare() */ + trace_volume_with_ids(dev, "vol->initial_ramp = %d, vol->ramp = %d, " "vol->min_value = %d, vol->max_value = %d", @@ -275,8 +290,12 @@ static int volume_params(struct comp_dev *dev, * \param[in,out] dev Volume base component device. * \param[in] chan Channel number. * \param[in] vol Target volume. + * \param[in] constant_rate_ramp When true do a constant rate + * and variable time length ramp. When false do + * a fixed length and variable rate ramp. */ -static inline int volume_set_chan(struct comp_dev *dev, int chan, int32_t vol) +static inline int volume_set_chan(struct comp_dev *dev, int chan, + int32_t vol, bool constant_rate_ramp) { struct comp_data *cd = comp_get_drvdata(dev); struct sof_ipc_comp_volume *pga = @@ -285,7 +304,6 @@ static inline int volume_set_chan(struct comp_dev *dev, int chan, int32_t vol) int32_t delta; int32_t delta_abs; int32_t inc; - int32_t t_us; /* Limit received volume gain to MIN..MAX range before applying it. * MAX is needed for now for the generic C gain arithmetics to prevent @@ -311,39 +329,41 @@ static inline int volume_set_chan(struct comp_dev *dev, int chan, int32_t vol) /* Check ramp type */ switch (pga->ramp) { case SOF_VOLUME_LINEAR: - - /* Assume the ramp length (initial_ramp [ms]) describes - * time of mute to 0 dB ramp. The actual volume scale min/max - * is not known. If initial_ramp is zero (or negative) use - * step size that reaches 0 dB gain in one step (VOL_ZERO_DB). - */ - if (pga->initial_ramp > 0) - inc = MAX(VOL_RAMP_STEP_CONST / pga->initial_ramp, 1); - else - inc = VOL_ZERO_DB; - - /* Scale the increment with actual volume range if it was - * passed via IPC. - */ - if (cd->vol_ramp_range) - inc = q_multsr_32x32(inc, cd->vol_ramp_range, - Q_SHIFT_BITS_32(VOL_QXY_Y, - VOL_QXY_Y, - VOL_QXY_Y)); - + /* Get volume transition delta and absolute value */ delta = cd->tvolume[chan] - cd->volume[chan]; delta_abs = ABS(delta); - /* If the ramp completion would take longer than initial_ramp - * increase the step size to make this ramp complete at - * initial_ramp time. Calculate estimated ramp length [us]. + /* The ramp length (initial_ramp [ms]) describes time of mute + * to vol_max unmuting. Normally the volume ramp has a + * constant linear slope defined this way and variable + * completion time. However in streaming start it is feasible + * to apply the entire topology defined ramp time to unmute to + * any used volume. In this case the ramp rate is not constant. + * Note also the legacy mode without known vol_ramp_range where + * the volume transition always uses the topology defined time. */ - t_us = delta_abs * VOL_RAMP_UPDATE_US / inc; - if (t_us > pga->initial_ramp * 1000) { - inc = (int32_t)((int64_t)inc * delta_abs / VOL_ZERO_DB); - inc = MAX(inc, 1); + if (pga->initial_ramp > 0) { + if (constant_rate_ramp && cd->vol_ramp_range > 0) + inc = q_multsr_32x32(cd->vol_ramp_range, + VOL_RAMP_STEP_CONST, + Q_MUL_SHIFT); + else + inc = q_multsr_32x32(delta_abs, + VOL_RAMP_STEP_CONST, + Q_MUL_SHIFT); + + /* Divide and round to nearest. Note that there will + * be some accumulated error in ramp time the longer + * the ramp and the smaller the transition is. + */ + inc = (2 * inc / pga->initial_ramp + 1) >> 1; + } else { + inc = delta_abs; } + /* Ensure inc is at least one */ + inc = MAX(inc, 1); + /* Invert sign for volume down ramp step */ if (delta < 0) inc = -inc; @@ -375,7 +395,7 @@ static inline void volume_set_chan_mute(struct comp_dev *dev, int chan) if (!cd->muted[chan]) { cd->mvolume[chan] = cd->tvolume[chan]; - volume_set_chan(dev, chan, 0); + volume_set_chan(dev, chan, 0, true); cd->muted[chan] = true; } } @@ -391,7 +411,7 @@ static inline void volume_set_chan_unmute(struct comp_dev *dev, int chan) if (cd->muted[chan]) { cd->muted[chan] = false; - volume_set_chan(dev, chan, cd->mvolume[chan]); + volume_set_chan(dev, chan, cd->mvolume[chan], true); } } @@ -438,7 +458,7 @@ static int volume_ctrl_set_cmd(struct comp_dev *dev, if (cd->muted[ch]) { cd->mvolume[ch] = val; } else { - ret = volume_set_chan(dev, ch, val); + ret = volume_set_chan(dev, ch, val, true); if (ret) return ret; } @@ -579,6 +599,10 @@ static int volume_copy(struct comp_dev *dev) tracev_volume_with_ids(dev, "volume_copy()"); + if (!cd->ramp_started) + schedule_task(&cd->volwork, VOL_RAMP_UPDATE_US, + VOL_RAMP_UPDATE_US); + /* Get source, sink, number of frames etc. to process. */ ret = comp_get_copy_limits(dev, &c); if (ret < 0) { @@ -652,8 +676,20 @@ static int volume_prepare(struct comp_dev *dev) goto err; } - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - vol_sync_host(cd, i); + vol_sync_host(cd, PLATFORM_MAX_CHANNELS); + + /* Set current volume to min to ensure ramp starts from minimum + * to previous volume request. Copy() checks for ramp started + * and schedules it if it has not yet started as result of + * driver commands. Ramp is not constant rate to ensure it lasts + * for entire topology specified time. + */ + cd->ramp_started = false; + cd->channels = sinkb->channels; + for (i = 0; i < cd->channels; i++) { + cd->volume[i] = cd->vol_min; + volume_set_chan(dev, i, cd->tvolume[i], false); + } return 0; diff --git a/src/include/sof/audio/volume.h b/src/include/sof/audio/volume.h index d57948e3dcff..b71c09da4f45 100644 --- a/src/include/sof/audio/volume.h +++ b/src/include/sof/audio/volume.h @@ -75,12 +75,13 @@ struct sof_ipc_ctrl_value_chan; /** * \brief Macro for volume linear gain ramp step computation * Volume gain ramp step as Q1.16 is computed with equation - * step = VOL_RAMP_STEP_CONST/ SOF_TKN_VOLUME_RAMP_STEP_MS. This + * step = VOL_RAMP_STEP_CONST / SOF_TKN_VOLUME_RAMP_STEP_MS. This * macro defines as Q1.16 value the constant term - * (1000 / VOL_RAMP_UPDATE) for step calculation. + * VOL_RAMP_UPDATE / 1000.0 for step calculation. The value 1000 + * is used to to convert microseconds to milliseconds. */ #define VOL_RAMP_STEP_CONST \ - Q_CONVERT_FLOAT(1000.0 / VOL_RAMP_UPDATE_US, VOL_QXY_Y) + Q_CONVERT_FLOAT(VOL_RAMP_UPDATE_US / 1000.0, VOL_QXY_Y) /** * \brief Volume maximum value. @@ -110,8 +111,10 @@ struct comp_data { int32_t vol_min; /**< minimum volume */ int32_t vol_max; /**< maximum volume */ int32_t vol_ramp_range; /**< max ramp transition */ + unsigned int channels; /**< current channels count */ bool muted[SOF_IPC_MAX_CHANNELS]; /**< set if channel is muted */ bool vol_ramp_active; /**< set if volume is ramped */ + bool ramp_started; /**< control ramp launch */ /**< volume processing function */ void (*scale_vol)(struct comp_dev *dev, struct comp_buffer *sink, struct comp_buffer *source, uint32_t frames); diff --git a/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt new file mode 100644 index 000000000000..b8a91e11868f --- /dev/null +++ b/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt @@ -0,0 +1 @@ +4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3225193546,2143508228,537150400,3220666496,537150400,0,32690, diff --git a/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt new file mode 100644 index 000000000000..d5077e402bfd --- /dev/null +++ b/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt @@ -0,0 +1 @@ +4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,32690, diff --git a/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt new file mode 100644 index 000000000000..ebbd75c3c248 --- /dev/null +++ b/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt @@ -0,0 +1 @@ +4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,0,32690, diff --git a/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt new file mode 100644 index 000000000000..19d82f920b67 --- /dev/null +++ b/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt @@ -0,0 +1 @@ +4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3231118179,2137545158,535660909,3223645479,535660909,0,32690, diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 new file mode 100644 index 000000000000..cb1fd5451898 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 @@ -0,0 +1,18 @@ +# 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP20HZ0dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0,' +` 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f,' +` 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 new file mode 100644 index 000000000000..669c9f3483b8 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 @@ -0,0 +1,18 @@ +# 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP20HZ0dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0,' +` 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20,' +` 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 new file mode 100644 index 000000000000..be0e3d70736e --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 @@ -0,0 +1,18 @@ +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0,' +` 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f,' +` 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 new file mode 100644 index 000000000000..a93f8cb8e15b --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 @@ -0,0 +1,18 @@ +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0,' +` 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20,' +` 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 new file mode 100644 index 000000000000..03be97e82651 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 @@ -0,0 +1,18 @@ +# 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP30HZ0dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1,' +` 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f,' +` 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 new file mode 100644 index 000000000000..a77770b613ac --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 @@ -0,0 +1,18 @@ +# 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP30HZ0dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0,' +` 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f,' +` 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 new file mode 100644 index 000000000000..7f2445d82416 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 @@ -0,0 +1,18 @@ +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1,' +` 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f,' +` 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 new file mode 100644 index 000000000000..88a62e7e12e3 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 @@ -0,0 +1,18 @@ +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0,' +` 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f,' +` 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 new file mode 100644 index 000000000000..5242fc4bc9e9 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 @@ -0,0 +1,18 @@ +# 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP40HZ0dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1,' +` 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f,' +` 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 new file mode 100644 index 000000000000..ea28ad008dcd --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 @@ -0,0 +1,18 @@ +# 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP40HZ0dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0,' +` 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f,' +` 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 new file mode 100644 index 000000000000..d2eb866d312e --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 @@ -0,0 +1,18 @@ +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1,' +` 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f,' +` 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 new file mode 100644 index 000000000000..d1e8d5f635c4 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 @@ -0,0 +1,18 @@ +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0,' +` 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f,' +` 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 new file mode 100644 index 000000000000..4d59264b2337 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 @@ -0,0 +1,18 @@ +# 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP50HZ0dB16K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x57,0xb1,0xc0,0xc1,' +` 0xd2,0x13,0x39,0x7e,0x45,0x3b,0xa2,0x1f,' +` 0x76,0x89,0xbb,0xc0,0x45,0x3b,0xa2,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 b/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 new file mode 100644 index 000000000000..11457d497d62 --- /dev/null +++ b/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 @@ -0,0 +1,18 @@ +# 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 +CONTROLBYTES_PRIV(EQIIR_HP50HZ0dB48K_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x63,0xf3,0x96,0xc0,' +` 0xc6,0x59,0x68,0x7f,0x6d,0x89,0xed,0x1f,' +` 0x27,0xed,0x24,0xc0,0x6d,0x89,0xed,0x1f,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/sof-hda-generic.m4 b/tools/topology/sof-hda-generic.m4 index 7feef6370b40..9544b20348a9 100644 --- a/tools/topology/sof-hda-generic.m4 +++ b/tools/topology/sof-hda-generic.m4 @@ -30,11 +30,13 @@ include(`platform/intel/intel-generic-dmic.m4') # # Define the pipelines # -# PCM0 <---> volume (pipe 1,2) <----> HDA Analog (HDA Analog playback/capture) -# PCM1 <---> volume (pipe 3,4) <----> HDA Digital (HDA Digital playback/capture) -# PCM3 ----> volume (pipe 7) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM4 ----> Volume (pipe 8) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM5 ----> volume (pipe 9) -----> iDisp3 (HDMI/DP playback, BE link 5) +# PCM0P --> volume (pipe 1) --> HDA Analog (HDA Analog playback) +# PCM0C <-- volume, EQ (pipe 2) <-- HDA Analog (HDA Analog capture) +# PCM1P --> volume (pipe 3) --> HDA Digital (HDA Digital playback) +# PCM1C <-- volume, EQ (pipe 4) <-- HDA Digital (HDA Digital capture) +# PCM3 ----> volume (pipe 7) ----> iDisp1 (HDMI/DP playback, BE link 3) +# PCM4 ----> Volume (pipe 8) ----> iDisp2 (HDMI/DP playback, BE link 4) +# PCM5 ----> volume (pipe 9) ----> iDisp3 (HDMI/DP playback, BE link 5) # # Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s24le. @@ -46,7 +48,7 @@ PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, # Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. # 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, 2, 0, 2, s24le, 1000, 0, 0, 48000, 48000, 48000) @@ -60,7 +62,7 @@ PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, # Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s24le. # 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, 4, 1, 2, s24le, 1000, 0, 0, 48000, 48000, 48000) diff --git a/tools/topology/sof/pipe-highpass-capture.m4 b/tools/topology/sof/pipe-highpass-capture.m4 new file mode 100644 index 000000000000..ecc2a8495911 --- /dev/null +++ b/tools/topology/sof/pipe-highpass-capture.m4 @@ -0,0 +1,123 @@ +# IIR highpass filter, volume control, and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQ_IIR <-- B2 <-- source DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# +# Volume Configuration +# + +define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(MY_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) +W_VENDORTUPLES(MY_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "400"')) + +W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) + +# +# IIR configuration +# + +include(`eq_iir_coef_highpass_40hz_0db_48khz.m4') + +# EQ Bytes control with max value of 255 +define(MY_EQIIR_BYTES, concat(`eqiir_bytes_', PIPELINE_ID)) +C_CONTROLBYTES(MY_EQIIR_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + EQIIR_HP40HZ0dB48K_priv) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) + +# "Volume" has 2 sink and 2 source periods +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, MY_PGA_CONF, + LIST(` ', "PIPELINE_ID Master Capture Volume")) + +# "EQ_IIR 0" has 2 sink and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, + LIST(` ', "MY_EQIIR_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_PGA_TOKENS') +undefine(`MY_PGA_CONF') +undefine(`MY_EQIIR_BYTES') diff --git a/tools/tune/eq/example_iir_eq.m b/tools/tune/eq/example_iir_eq.m index 496bc280fa2b..dd5fa9142908 100644 --- a/tools/tune/eq/example_iir_eq.m +++ b/tools/tune/eq/example_iir_eq.m @@ -116,37 +116,11 @@ function example_iir_eq() bp = eq_iir_blob_pack(bm); eq_alsactl_write(alsa_fn, bp); -%% ------------------------------------ -%% Example 4: 50 Hz high-pass with gain -%% ------------------------------------ -tplg_fn = '../../topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4'; -comment = '50 Hz second order high-pass and +20 dB gain'; - -%% Design IIR high-pass -eq_hp = hp_iir_eq(fs); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_hp = eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One responses: hp -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_hp); - -%% Pack and write file. If there are several EQ instances need -%% to have identifier string to get correct response to each -%% instance (here _HP50HZ20dB48K) and refer to in topology. -bp = eq_iir_blob_pack(bm); -eq_tplg_write(tplg_fn, bp, 'IIR_HP50HZ20dB48K', comment); %% ------------------- -%% Example 5: Flat IIR +%% Example 4: Flat IIR %% ------------------- -comment = 'Flat IIR EQ'; +comment = 'Flat IIR EQ, created with example_iir_eq.m'; alsa_fn = '../../ctl/eq_iir_flat.txt'; tplg_fn = '../../topology/m4/eq_iir_coef_flat.m4'; @@ -171,7 +145,7 @@ function example_iir_eq() eq_tplg_write(tplg_fn, bp, 'IIR', comment); %% --------------------------- -%% Example 6: Pass-through IIR +%% Example 5: Pass-through IIR %% ------------------------------------ alsa_fn = '../../ctl/eq_iir_pass.txt'; @@ -194,32 +168,54 @@ function example_iir_eq() bp = eq_iir_blob_pack(bm); eq_alsactl_write(alsa_fn, bp); -%% -------------------------------------------- -%% Example 7: 50 Hz high-pass with gain, 16 kHz -%% -------------------------------------------- -tplg_fn = '../../topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4'; -comment = '50 Hz second order high-pass and +20 dB gain'; - -%% Design IIR high-pass -eq_hp = hp_iir_eq(16e3); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_hp = eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One response: hp -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_hp); +%% ------------------------------------ +%% Example 6: 20/30/40/50 Hz high-pass +%% ------------------------------------ -%% Pack and write file. If there are several EQ instances need -%% to have identifier string to get correct response to each -%% instance (here _HP50HZ20dB16K) and refer to in topology. -bp = eq_iir_blob_pack(bm); -eq_tplg_write(tplg_fn, bp, 'IIR_HP50HZ20dB16K', comment); +tpath = '../../topology/m4'; +cpath = '../../ctl'; +fs_list = [16e3 48e3]; +fc_list = [20 30 40 50]; +g_list = [0 20]; +for i = 1:length(fs_list) + for j = 1:length(fc_list); + for k = 1:length(g_list); + fs = fs_list(i); + fc = fc_list(j); + g = g_list(k); + fsk = round(fs/1e3); + tplg_fn = sprintf('%s/eq_iir_coef_highpass_%dhz_%ddb_%dkhz.m4', ... + tpath, fc, g, fsk); + alsa_fn = sprintf('%s/eq_iir_highpass_%dhz_%ddb_%dkhz.txt', ... + cpath, fc, g, fsk); + comment = sprintf('%d Hz second order high-pass, gain %d dB, created with example_iir_eq.m', ... + fc, g); + tpid = sprintf('IIR_HP%dHZ%ddB%dK', fc, g, fsk); + + %% Design IIR high-pass + eq_hp = hp_iir_eq(fs, fc, 0); + + %% Quantize and pack filter coefficients plus shifts etc. + bq_hp = eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); + + %% Build blob + channels_in_config = 2; % Setup max 2 channels EQ + assign_response = [0 0]; % Switch to response #0 + num_responses = 1; % One responses: hp + bm = eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_hp); + + %% Pack and write file. If there are several EQ instances need + %% to have identifier string to get correct response to each + %% instance (here _HP50HZ20dB48K) and refer to in topology. + bp = eq_iir_blob_pack(bm); + eq_tplg_write(tplg_fn, bp, tpid, comment); + eq_alsactl_write(alsa_fn, bp); + end + end +end end @@ -287,17 +283,17 @@ function example_iir_eq() end -function eq = hp_iir_eq(fs) +function eq = hp_iir_eq(fs, fc, gain_db) % Get defaults for equalizer design eq = eq_defaults(); eq.fs = fs; eq.enable_iir = 1; eq.norm_type = '1k'; -eq.norm_offs_db = 20; +eq.norm_offs_db = gain_db; % Design -eq.peq = [ eq.PEQ_HP2 50 NaN NaN ]; +eq.peq = [ eq.PEQ_HP2 fc NaN NaN ]; eq = eq_compute(eq); eq_plot(eq);