diff --git a/topology/nhlt/intel/ssp-nhlt.c b/topology/nhlt/intel/ssp-nhlt.c index cd22d39..4a6980f 100644 --- a/topology/nhlt/intel/ssp-nhlt.c +++ b/topology/nhlt/intel/ssp-nhlt.c @@ -16,41 +16,330 @@ #include "intel-nhlt.h" #include "ssp-nhlt.h" #include "ssp/ssp-process.h" +#include "ssp/ssp-internal.h" -static int set_ssp_data(struct intel_nhlt_params *nhlt, snd_config_t *dai_cfg, snd_config_t *top) +static int set_mn_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) { - const char *tdm_padding_per_slot = NULL; - const char *direction = NULL; - const char *quirks = NULL; - long frame_pulse_width = 0; - long clks_control = 0; - long sample_bits = 0; - long bclk_delay = 0; - long dai_index = 0; - long mclk_id = 0; - long io_clk = 0; - int ret; + long m_div; + long n_div; + long ret; - struct dai_values ssp_data[] = { - { "io_clk", SND_CONFIG_TYPE_INTEGER, NULL, &io_clk, NULL}, - { "direction", SND_CONFIG_TYPE_STRING, NULL, NULL, &direction}, - { "quirks", SND_CONFIG_TYPE_STRING, NULL, NULL, &quirks}, - { "dai_index", SND_CONFIG_TYPE_INTEGER, NULL, &dai_index, NULL}, - { "sample_bits", SND_CONFIG_TYPE_INTEGER, NULL, &sample_bits, NULL}, - { "bclk_delay", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_delay, NULL}, - { "mclk_id", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_id, NULL}, - { "clks_control", SND_CONFIG_TYPE_INTEGER, NULL, &clks_control, NULL}, - { "frame_pulse_width", SND_CONFIG_TYPE_INTEGER, NULL, &frame_pulse_width, NULL}, - { "tdm_padding_per_slot", SND_CONFIG_TYPE_STRING, NULL, NULL, - &tdm_padding_per_slot}, + struct dai_values ssp_mn_data[] = { + {"m_div", SND_CONFIG_TYPE_INTEGER, NULL, &m_div, NULL}, + {"n_div", SND_CONFIG_TYPE_INTEGER, NULL, &n_div, NULL}, }; - ret = find_set_values(&ssp_data[0], ARRAY_SIZE(ssp_data), dai_cfg, top, "Class.Dai.SSP"); + ret = find_set_values(&ssp_mn_data[0], ARRAY_SIZE(ssp_mn_data), cfg, top, + "Class.Base.mn_config"); if (ret < 0) return ret; - return ssp_set_params(nhlt, direction, dai_index, io_clk, bclk_delay, sample_bits, mclk_id, - clks_control, frame_pulse_width, tdm_padding_per_slot, quirks); + return ssp_mn_set_params(nhlt, m_div, n_div); +} + +static int set_clk_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long clock_warm_up; + long mclk; + long warm_up_ovr; + long clock_stop_delay; + long keep_running; + long clock_stop_ovr; + long ret; + + struct dai_values ssp_clk_data[] = { + {"clock_warm_up", SND_CONFIG_TYPE_INTEGER, NULL, &clock_warm_up, NULL}, + {"mclk", SND_CONFIG_TYPE_INTEGER, NULL, &mclk, NULL}, + {"warm_up_ovr", SND_CONFIG_TYPE_INTEGER, NULL, &warm_up_ovr, NULL}, + {"clock_stop_delay", SND_CONFIG_TYPE_INTEGER, NULL, &clock_stop_delay, NULL}, + {"keep_running", SND_CONFIG_TYPE_INTEGER, NULL, &keep_running, NULL}, + {"clock_stop_ovr", SND_CONFIG_TYPE_INTEGER, NULL, &clock_stop_ovr, NULL}, + }; + + ret = find_set_values(&ssp_clk_data[0], ARRAY_SIZE(ssp_clk_data), cfg, top, + "Class.Base.clk_config"); + if (ret < 0) + return ret; + + return ssp_clk_set_params(nhlt, clock_warm_up, mclk, warm_up_ovr, clock_stop_delay, + keep_running, clock_stop_ovr); +} + +static int set_tr_start_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long sampling_frequency; + long bit_depth; + long channel_map; + long channel_config; + long interleaving_style; + long number_of_channels; + long valid_bit_depth; + long sample_type; + long ret; + + struct dai_values ssp_tr_data[] = { + {"sampling_frequency", SND_CONFIG_TYPE_INTEGER, NULL, &sampling_frequency, NULL}, + {"bit_depth", SND_CONFIG_TYPE_INTEGER, NULL, &bit_depth, NULL}, + {"channel_map", SND_CONFIG_TYPE_INTEGER, NULL, &channel_map, NULL}, + {"channel_config", SND_CONFIG_TYPE_INTEGER, NULL, &channel_config, NULL}, + {"interleaving_style", SND_CONFIG_TYPE_INTEGER, NULL, &interleaving_style, NULL}, + {"number_of_channels", SND_CONFIG_TYPE_INTEGER, NULL, &number_of_channels, NULL}, + {"valid_bit_depth", SND_CONFIG_TYPE_INTEGER, NULL, &valid_bit_depth, NULL}, + {"sample_type", SND_CONFIG_TYPE_INTEGER, NULL, &sample_type, NULL}, + }; + + ret = find_set_values(&ssp_tr_data[0], ARRAY_SIZE(ssp_tr_data), cfg, top, + "Class.Base.tr_start_config"); + if (ret < 0) + return ret; + + return ssp_tr_start_set_params(nhlt, sampling_frequency, bit_depth, channel_map, + channel_config, interleaving_style, number_of_channels, + valid_bit_depth,sample_type); +} + +static int set_tr_stop_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long sampling_frequency; + long bit_depth; + long channel_map; + long channel_config; + long interleaving_style; + long number_of_channels; + long valid_bit_depth; + long sample_type; + long ret; + + struct dai_values ssp_tr_data[] = { + {"sampling_frequency", SND_CONFIG_TYPE_INTEGER, NULL, &sampling_frequency, NULL}, + {"bit_depth", SND_CONFIG_TYPE_INTEGER, NULL, &bit_depth, NULL}, + {"channel_map", SND_CONFIG_TYPE_INTEGER, NULL, &channel_map, NULL}, + {"channel_config", SND_CONFIG_TYPE_INTEGER, NULL, &channel_config, NULL}, + {"interleaving_style", SND_CONFIG_TYPE_INTEGER, NULL, &interleaving_style, NULL}, + {"number_of_channels", SND_CONFIG_TYPE_INTEGER, NULL, &number_of_channels, NULL}, + {"valid_bit_depth", SND_CONFIG_TYPE_INTEGER, NULL, &valid_bit_depth, NULL}, + {"sample_type", SND_CONFIG_TYPE_INTEGER, NULL, &sample_type, NULL}, + }; + + ret = find_set_values(&ssp_tr_data[0], ARRAY_SIZE(ssp_tr_data), cfg, top, + "Class.Base.tr_stop_config"); + if (ret < 0) + return ret; + + return ssp_tr_stop_set_params(nhlt, sampling_frequency, bit_depth, channel_map, + channel_config, interleaving_style, number_of_channels, + valid_bit_depth,sample_type); +} + +static int set_run_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long always_run; + long ret; + + struct dai_values ssp_run_data[] = { + {"always_run", SND_CONFIG_TYPE_INTEGER, NULL, &always_run, NULL}, + }; + + ret = find_set_values(&ssp_run_data[0], ARRAY_SIZE(ssp_run_data), cfg, top, + "Class.Base.run_config"); + if (ret < 0) + return ret; + + return ssp_run_set_params(nhlt, always_run); +} + +static int set_node_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long sampling_rate; + long node_id; + long ret; + + struct dai_values ssp_node_data[] = { + {"node_id", SND_CONFIG_TYPE_INTEGER, NULL, &node_id, NULL}, + {"sampling_rate", SND_CONFIG_TYPE_INTEGER, NULL, &sampling_rate, NULL}, + }; + + ret = find_set_values(&ssp_node_data[0], ARRAY_SIZE(ssp_node_data), cfg, top, + "Class.Base.node_config"); + if (ret < 0) + return ret; + + return ssp_node_set_params(nhlt, node_id, sampling_rate); +} + +static int set_sync_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long sync_denominator; + long ret; + + struct dai_values ssp_sync_data[] = { + {"sync_denominator", SND_CONFIG_TYPE_INTEGER, NULL, &sync_denominator, NULL}, + }; + + ret = find_set_values(&ssp_sync_data[0], ARRAY_SIZE(ssp_sync_data), cfg, top, + "Class.Base.sync_config"); + if (ret < 0) + return ret; + + return ssp_sync_set_params(nhlt, sync_denominator); +} + +static int set_ext_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long mclk_policy_override; + long mclk_always_running; + long mclk_starts_on_gtw_init; + long mclk_starts_on_run; + long mclk_starts_on_pause; + long mclk_stops_on_pause; + long mclk_stops_on_reset; + + long bclk_policy_override; + long bclk_always_running; + long bclk_starts_on_gtw_init; + long bclk_starts_on_run; + long bclk_starts_on_pause; + long bclk_stops_on_pause; + long bclk_stops_on_reset; + + long sync_policy_override; + long sync_always_running; + long sync_starts_on_gtw_init; + long sync_starts_on_run; + long sync_starts_on_pause; + long sync_stops_on_pause; + long sync_stops_on_reset; + long ret; + + struct dai_values ssp_ext_data[] = { + {"mclk_policy_override", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_policy_override, NULL}, + {"mclk_always_running", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_always_running, NULL}, + {"mclk_starts_on_gtw_init", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_starts_on_gtw_init, NULL}, + {"mclk_starts_on_run", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_starts_on_run, NULL}, + {"mclk_starts_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_starts_on_pause, NULL}, + {"mclk_stops_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_stops_on_pause, NULL}, + {"mclk_stops_on_reset", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_stops_on_reset, NULL}, + {"bclk_policy_override", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_policy_override, NULL}, + {"bclk_always_running", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_always_running, NULL}, + {"bclk_starts_on_gtw_init", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_starts_on_gtw_init, NULL}, + {"bclk_starts_on_run", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_starts_on_run, NULL}, + {"bclk_starts_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_starts_on_pause, NULL}, + {"bclk_stops_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_stops_on_pause, NULL}, + {"bclk_stops_on_reset", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_stops_on_reset, NULL}, + {"sync_policy_override", SND_CONFIG_TYPE_INTEGER, NULL, &sync_policy_override, NULL}, + {"sync_always_running", SND_CONFIG_TYPE_INTEGER, NULL, &sync_always_running, NULL}, + {"sync_starts_on_gtw_init", SND_CONFIG_TYPE_INTEGER, NULL, &sync_starts_on_gtw_init, NULL}, + {"sync_starts_on_run", SND_CONFIG_TYPE_INTEGER, NULL, &sync_starts_on_run, NULL}, + {"sync_starts_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &sync_starts_on_pause, NULL}, + {"sync_stops_on_pause", SND_CONFIG_TYPE_INTEGER, NULL, &sync_stops_on_pause, NULL}, + {"sync_stops_on_reset", SND_CONFIG_TYPE_INTEGER, NULL, &sync_stops_on_reset, NULL}, + }; + + ret = find_set_values(&ssp_ext_data[0], ARRAY_SIZE(ssp_ext_data), cfg, top, + "Class.Base.ext_config"); + if (ret < 0) + return ret; + + return ssp_ext_set_params(nhlt, mclk_policy_override, mclk_always_running, + mclk_starts_on_gtw_init, mclk_starts_on_run, mclk_starts_on_pause, + mclk_stops_on_pause, mclk_stops_on_reset, + bclk_policy_override, bclk_always_running, + bclk_starts_on_gtw_init, bclk_starts_on_run, bclk_starts_on_pause, + bclk_stops_on_pause, bclk_stops_on_reset, + sync_policy_override, sync_always_running, + sync_starts_on_gtw_init, sync_starts_on_run, sync_starts_on_pause, + sync_stops_on_pause, sync_stops_on_reset); +} + +static int set_link_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + long clock_source; + long ret; + + struct dai_values ssp_link_data[] = { + {"clock_source", SND_CONFIG_TYPE_INTEGER, NULL, &clock_source, NULL}, + }; + + ret = find_set_values(&ssp_link_data[0], ARRAY_SIZE(ssp_link_data), cfg, top, + "Class.Base.link_config"); + if (ret < 0) + return ret; + + return ssp_link_set_params(nhlt, clock_source); +} + +static int set_aux_params(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) +{ + struct aux_map { + const char *name; + int id; + }; + + struct aux_map aux_maps[] = { + { "Object.Base.mn_config", SSP_MN_DIVIDER_CONTROLS }, + {"Object.Base.clk_config", SSP_DMA_CLK_CONTROLS }, + {"Object.Base.tr_start_config", SSP_DMA_TRANSMISSION_START }, + {"Object.Base.tr_stop_config", SSP_DMA_TRANSMISSION_STOP }, + {"Object.Base.run_config", SSP_DMA_ALWAYS_RUNNING_MODE} , + {"Object.Base.sync_config", SSP_DMA_SYNC_DATA }, + {"Object.Base.ext_config", SSP_DMA_CLK_CONTROLS_EXT }, + {"Object.Base.link_config", SSP_LINK_CLK_SOURCE }, + {"Object.Base.node_config", SSP_DMA_SYNC_NODE }, + }; + + snd_config_iterator_t iter, next; + snd_config_t *items, *n; + const char *id; + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(aux_maps); i++) { + if (snd_config_search(cfg, aux_maps[i].name, &items) < 0) + continue; + + snd_config_for_each(iter, next, items) { + n = snd_config_iterator_entry(iter); + + if (snd_config_get_id(n, &id) < 0) + continue; + + switch(aux_maps[i].id) { + case SSP_MN_DIVIDER_CONTROLS: + ret = set_mn_config(nhlt, n, top); + break; + case SSP_DMA_CLK_CONTROLS: + ret = set_clk_config(nhlt, n, top); + break; + case SSP_DMA_TRANSMISSION_START: + ret = set_tr_start_config(nhlt, n, top); + break; + case SSP_DMA_TRANSMISSION_STOP: + ret = set_tr_stop_config(nhlt, n, top); + break; + case SSP_DMA_ALWAYS_RUNNING_MODE: + ret = set_run_config(nhlt, n, top); + break; + case SSP_DMA_SYNC_DATA: + ret = set_sync_config(nhlt, n, top); + break; + case SSP_DMA_CLK_CONTROLS_EXT: + ret = set_ext_config(nhlt, n, top); + break; + case SSP_LINK_CLK_SOURCE: + ret = set_link_config(nhlt, n, top); + break; + case SSP_DMA_SYNC_NODE: + ret = set_node_config(nhlt, n, top); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + } + } + + return ret; } static int set_hw_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_config_t *top) @@ -91,11 +380,51 @@ static int set_hw_config(struct intel_nhlt_params *nhlt, snd_config_t *cfg, snd_ if (ret < 0) return ret; + ret = set_aux_params(nhlt, cfg, top); + if (ret < 0) + return ret; + return ssp_hw_set_params(nhlt, format, mclk, bclk, bclk_invert, fsync, fsync_invert, mclk_freq, bclk_freq, fsync_freq, tdm_slots, tdm_slot_width, tx_slots, rx_slots); } +static int set_ssp_data(struct intel_nhlt_params *nhlt, snd_config_t *dai_cfg, snd_config_t *top) +{ + const char *tdm_padding_per_slot = NULL; + const char *direction = NULL; + const char *quirks = NULL; + long frame_pulse_width = 0; + long clks_control = 0; + long sample_bits = 0; + long bclk_delay = 0; + long dai_index = 0; + long mclk_id = 0; + long io_clk = 0; + int ret; + + struct dai_values ssp_data[] = { + { "io_clk", SND_CONFIG_TYPE_INTEGER, NULL, &io_clk, NULL}, + { "direction", SND_CONFIG_TYPE_STRING, NULL, NULL, &direction}, + { "quirks", SND_CONFIG_TYPE_STRING, NULL, NULL, &quirks}, + { "dai_index", SND_CONFIG_TYPE_INTEGER, NULL, &dai_index, NULL}, + { "sample_bits", SND_CONFIG_TYPE_INTEGER, NULL, &sample_bits, NULL}, + { "bclk_delay", SND_CONFIG_TYPE_INTEGER, NULL, &bclk_delay, NULL}, + { "mclk_id", SND_CONFIG_TYPE_INTEGER, NULL, &mclk_id, NULL}, + { "clks_control", SND_CONFIG_TYPE_INTEGER, NULL, &clks_control, NULL}, + { "frame_pulse_width", SND_CONFIG_TYPE_INTEGER, NULL, &frame_pulse_width, NULL}, + { "tdm_padding_per_slot", SND_CONFIG_TYPE_STRING, NULL, NULL, + &tdm_padding_per_slot}, + }; + + ret = find_set_values(&ssp_data[0], ARRAY_SIZE(ssp_data), dai_cfg, top, "Class.Dai.SSP"); + if (ret < 0) + return ret; + + return ssp_set_params(nhlt, direction, dai_index, io_clk, bclk_delay, sample_bits, mclk_id, + clks_control, frame_pulse_width, tdm_padding_per_slot, quirks); +} + /* init ssp parameters, should be called before parsing dais */ int nhlt_ssp_init_params(struct intel_nhlt_params *nhlt) { @@ -194,7 +523,7 @@ int nhlt_ssp_get_ep(struct intel_nhlt_params *nhlt, struct endpoint_descriptor * f_conf1[i].format.SubFormat[2] = 0; f_conf1[i].format.SubFormat[3] = 0; - ret = ssp_get_vendor_blob_size(nhlt, &blob_size); + ret = ssp_get_vendor_blob_size(nhlt, dai_index, i, &blob_size); if (ret < 0) { fprintf(stderr, "nhlt_ssp_get_ep: dmic_get_vendor_blob_size failed\n"); return ret; diff --git a/topology/nhlt/intel/ssp/ssp-debug.c b/topology/nhlt/intel/ssp/ssp-debug.c index d14108d..3e73078 100644 --- a/topology/nhlt/intel/ssp/ssp-debug.c +++ b/topology/nhlt/intel/ssp/ssp-debug.c @@ -7,14 +7,17 @@ #include #include #include "ssp-debug.h" +#include "../intel-nhlt.h" #ifdef NHLT_DEBUG void ssp_print_calculated(struct intel_ssp_params *ssp) { struct ssp_intel_config_data *blob; + struct ssp_aux_blob *blob_aux; int ssp_index = ssp->ssp_count; - int i; + uint32_t *ptr; + int i, j; fprintf(stdout, "printing ssp nhlt calculated data:\n"); @@ -29,7 +32,7 @@ void ssp_print_calculated(struct intel_ssp_params *ssp) fprintf(stdout, "\n"); for (i = 0; i < ssp->ssp_hw_config_count[ssp_index]; i++) { - blob = &ssp->ssp_blob[ssp->ssp_count][i]; + blob = &ssp->ssp_blob[ssp_index][i]; fprintf(stdout, "ssp blob %d hw_config %d\n", ssp->ssp_count, i); fprintf(stdout, "gateway_attributes %u\n", blob->gateway_attributes); fprintf(stdout, "ts_group[0] 0x%08x\n", blob->ts_group[0]); @@ -52,6 +55,15 @@ void ssp_print_calculated(struct intel_ssp_params *ssp) fprintf(stdout, "ssioc 0x%08x\n", blob->ssioc); fprintf(stdout, "mdivc 0x%08x\n", blob->mdivc); fprintf(stdout, "mdivr 0x%08x\n", blob->mdivr); + + blob_aux = (struct ssp_aux_blob *)&(ssp->ssp_blob_ext[ssp_index][i]); + fprintf(stdout, "aux_blob size %u\n", blob_aux->size); + for (j = 0; j < blob_aux->size; j += 4) { + ptr = (uint32_t *)&(blob_aux->aux_blob[j]); + fprintf(stdout, "aux_blob %d 0x%08x\n", j, *ptr); + } + + fprintf(stdout, "\n"); } fprintf(stdout, "\n"); @@ -59,9 +71,17 @@ void ssp_print_calculated(struct intel_ssp_params *ssp) void ssp_print_internal(struct intel_ssp_params *ssp) { - struct ssp_config_hw *hw_conf; + struct ssp_aux_config_link *link; + struct ssp_aux_config_sync *sync; + struct ssp_aux_config_ext *ext; + struct ssp_aux_config_run *run; + struct ssp_aux_config_clk *clk; + struct ssp_aux_config_mn *mn; + struct ssp_aux_config_tr *tr; struct ssp_config_dai *dai; - int i; + struct ssp_config_hw *hw_conf; + uint32_t enabled; + int i, j; dai = &ssp->ssp_prm[ssp->ssp_count]; @@ -92,6 +112,106 @@ void ssp_print_internal(struct intel_ssp_params *ssp) fprintf(stdout, "tx_slots %u\n", hw_conf->tx_slots); fprintf(stdout, "rx_slots %u\n", hw_conf->rx_slots); fprintf(stdout, "format %u\n", hw_conf->format); + + enabled = dai->aux_cfg[i].enabled; + fprintf(stdout, "aux enabled %x\n", enabled); + fprintf(stdout, "\n"); + + mn = (struct ssp_aux_config_mn *)&(dai->aux_cfg[i].mn); + clk = (struct ssp_aux_config_clk *)&(dai->aux_cfg[i].clk); + tr = (struct ssp_aux_config_tr *)&(dai->aux_cfg[i].tr_start); + tr = (struct ssp_aux_config_tr *)&(dai->aux_cfg[i].tr_stop); + run = (struct ssp_aux_config_run *)&(dai->aux_cfg[i].run); + sync = (struct ssp_aux_config_sync *)&(dai->aux_cfg[i].sync); + ext = (struct ssp_aux_config_ext *)&(dai->aux_cfg[i].ext); + link = (struct ssp_aux_config_link *)&(dai->aux_cfg[i].link); + + if (enabled & BIT(SSP_MN_DIVIDER_CONTROLS)) { + fprintf(stdout, "aux mn m_div %u\n", mn->m_div); + fprintf(stdout, "aux mn n_div %u\n", mn->n_div); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_CLK_CONTROLS)) { + fprintf(stdout, "aux clk clock_warm_up %u\n", clk->clock_warm_up); + fprintf(stdout, "aux clk mclk %u\n", clk->mclk); + fprintf(stdout, "aux clk warm_up_ovr %u\n", clk->warm_up_ovr); + fprintf(stdout, "aux clk clock_stop_delay %u\n", clk->clock_stop_delay); + fprintf(stdout, "aux clk keep_running %u\n", clk->keep_running); + fprintf(stdout, "aux clk keep_running %u\n", clk->clock_stop_ovr); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_TRANSMISSION_START)) { + fprintf(stdout, "aux tr start sampling_frequency %u\n", tr->sampling_frequency); + fprintf(stdout, "aux tr start bit_depth %u\n", tr->bit_depth); + fprintf(stdout, "aux tr start channel_map %u\n", tr->channel_map); + fprintf(stdout, "aux tr start channel_config %u\n", tr->channel_config); + fprintf(stdout, "aux tr start interleaving_style %u\n", tr->interleaving_style); + fprintf(stdout, "aux tr start number_of_channels %u\n", tr->number_of_channels); + fprintf(stdout, "aux tr start valid_bit_depth %u\n", tr->valid_bit_depth); + fprintf(stdout, "aux tr start sample_types %u\n", tr->sample_type); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_TRANSMISSION_STOP)) { + fprintf(stdout, "aux tr start sampling_frequency %u\n", tr->sampling_frequency); + fprintf(stdout, "aux tr start bit_depth %u\n", tr->bit_depth); + fprintf(stdout, "aux tr start channel_map %u\n", tr->channel_map); + fprintf(stdout, "aux tr start channel_config %u\n", tr->channel_config); + fprintf(stdout, "aux tr start interleaving_style %u\n", tr->interleaving_style); + fprintf(stdout, "aux tr start number_of_channels %u\n", tr->number_of_channels); + fprintf(stdout, "aux tr start valid_bit_depth %u\n", tr->valid_bit_depth); + fprintf(stdout, "aux tr start sample_types %u\n", tr->sample_type); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_ALWAYS_RUNNING_MODE)) { + fprintf(stdout, "aux run always_run %u\n", run->always_run); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_SYNC_DATA)) { + fprintf(stdout, "aux sync sync_denominator %u\n", sync->sync_denominator); + fprintf(stdout, "aux sync count %u\n", sync->count); + + for (j = 0; j < sync->count; j++) { + fprintf(stdout, "aux sync node_id %u\n", sync->nodes[j].node_id); + fprintf(stdout, "aux sync sampling_rate %u\n", sync->nodes[j].sampling_rate); + } + + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_DMA_CLK_CONTROLS_EXT)) { + fprintf(stdout, "aux ext mclk_policy_override %u\n", ext->mclk_policy_override); + fprintf(stdout, "aux ext mclk_always_running %u\n", ext->mclk_always_running); + fprintf(stdout, "aux ext mclk_starts_on_gtw_init %u\n", ext->mclk_starts_on_gtw_init); + fprintf(stdout, "aux ext mclk_starts_on_run %u\n", ext->mclk_starts_on_run); + fprintf(stdout, "aux ext mclk_starts_on_pause %u\n", ext->mclk_starts_on_pause); + fprintf(stdout, "aux ext mclk_stops_on_pause %u\n", ext->mclk_stops_on_pause); + fprintf(stdout, "aux ext mclk_stops_on_reset %u\n", ext->mclk_stops_on_reset); + fprintf(stdout, "aux ext bclk_policy_override %u\n", ext->bclk_policy_override); + fprintf(stdout, "aux ext bclk_always_running %u\n", ext->bclk_always_running); + fprintf(stdout, "aux ext bclk_starts_on_gtw_init %u\n", ext->bclk_starts_on_gtw_init); + fprintf(stdout, "aux ext bclk_starts_on_run %u\n", ext->bclk_starts_on_run); + fprintf(stdout, "aux ext bclk_starts_on_pause %u\n", ext->bclk_starts_on_pause); + fprintf(stdout, "aux ext bclk_stops_on_pause %u\n", ext->bclk_stops_on_pause); + fprintf(stdout, "aux ext bclk_stops_on_reset %u\n", ext->bclk_stops_on_reset); + fprintf(stdout, "aux ext sync_policy_override %u\n", ext->sync_policy_override); + fprintf(stdout, "aux ext sync_always_running %u\n", ext->sync_always_running); + fprintf(stdout, "aux ext sync_starts_on_gtw_init %u\n", ext->sync_starts_on_gtw_init); + fprintf(stdout, "aux ext sync_starts_on_run %u\n", ext->sync_starts_on_run); + fprintf(stdout, "aux ext sync_starts_on_pause %u\n", ext->sync_starts_on_pause); + fprintf(stdout, "aux ext sync_stops_on_pause %u\n", ext->sync_stops_on_pause); + fprintf(stdout, "aux ext sync_stops_on_reset %u\n", ext->sync_stops_on_reset); + fprintf(stdout, "\n"); + } + + if (enabled & BIT(SSP_LINK_CLK_SOURCE)) { + fprintf(stdout, "aux link clock_source %u\n", link->clock_source); + fprintf(stdout, "\n"); + } } fprintf(stdout, "\n"); diff --git a/topology/nhlt/intel/ssp/ssp-intel.h b/topology/nhlt/intel/ssp/ssp-intel.h index b2dee4a..9c92424 100644 --- a/topology/nhlt/intel/ssp/ssp-intel.h +++ b/topology/nhlt/intel/ssp/ssp-intel.h @@ -52,4 +52,51 @@ struct ssp_intel_config_data_1_5 { uint32_t mdivr[]; } __attribute__((packed)); +struct ssp_intel_aux_tlv { + uint32_t type; + uint32_t size; + uint32_t val[]; +} __attribute__((packed)); + +struct ssp_intel_mn_ctl { + uint32_t div_m; + uint32_t div_n; +} __attribute__((packed)); + +struct ssp_intel_clk_ctl { + uint32_t start; + uint32_t stop; +} __attribute__((packed)); + +struct ssp_intel_tr_ctl { + uint32_t sampling_frequency; + uint32_t bit_depth; + uint32_t channel_map; + uint32_t channel_config; + uint32_t interleaving_style; + uint32_t format; +} __attribute__((packed)); + +struct ssp_intel_run_ctl { + uint32_t enabled; +} __attribute__((packed)); + +struct ssp_intel_node_ctl { + uint32_t node_id; + uint32_t sampling_rate; +} __attribute__((packed)); + +struct ssp_intel_sync_ctl { + uint32_t sync_denominator; + uint32_t count; +} __attribute__((packed)); + +struct ssp_intel_ext_ctl { + uint32_t ext_data; +} __attribute__((packed)); + +struct ssp_intel_link_ctl { + uint32_t clock_source; +} __attribute__((packed)); + #endif /* __SSP_INTEL_H */ diff --git a/topology/nhlt/intel/ssp/ssp-internal.h b/topology/nhlt/intel/ssp/ssp-internal.h index bf88a37..6c2894e 100644 --- a/topology/nhlt/intel/ssp/ssp-internal.h +++ b/topology/nhlt/intel/ssp/ssp-internal.h @@ -16,7 +16,91 @@ #define SSP_MAX_HW_CONFIG 8 #define SSP_TDM_MAX_SLOT_MAP_COUNT 8 +struct ssp_aux_config_mn { + uint32_t m_div; + uint32_t n_div; +}; +struct ssp_aux_config_clk { + uint32_t clock_warm_up; + uint32_t mclk; + uint32_t warm_up_ovr; + uint32_t clock_stop_delay; + uint32_t keep_running; + uint32_t clock_stop_ovr; +}; + +struct ssp_aux_config_tr { + uint32_t sampling_frequency; + uint32_t bit_depth; + uint32_t channel_map; + uint32_t channel_config; + uint32_t interleaving_style; + uint32_t number_of_channels; + uint32_t valid_bit_depth; + uint32_t sample_type; +}; + +struct ssp_aux_config_run { + uint32_t always_run; +}; + +struct ssp_aux_config_node { + uint32_t node_id; + uint32_t sampling_rate; +}; + +struct ssp_aux_config_sync { + uint32_t sync_denominator; + uint32_t count; + struct ssp_aux_config_node nodes[SSP_MAX_DAIS]; +}; + +struct ssp_aux_config_ext { + uint32_t mclk_policy_override; + uint32_t mclk_always_running; + uint32_t mclk_starts_on_gtw_init; + uint32_t mclk_starts_on_run; + uint32_t mclk_starts_on_pause; + uint32_t mclk_stops_on_pause; + uint32_t mclk_stops_on_reset; + uint32_t bclk_policy_override; + uint32_t bclk_always_running; + uint32_t bclk_starts_on_gtw_init; + uint32_t bclk_starts_on_run; + uint32_t bclk_starts_on_pause; + uint32_t bclk_stops_on_pause; + uint32_t bclk_stops_on_reset; + uint32_t sync_policy_override; + uint32_t sync_always_running; + uint32_t sync_starts_on_gtw_init; + uint32_t sync_starts_on_run; + uint32_t sync_starts_on_pause; + uint32_t sync_stops_on_pause; + uint32_t sync_stops_on_reset; +}; + +struct ssp_aux_config_link { + uint32_t clock_source; +}; + +struct ssp_config_aux { + /* bits set for found aux structs */ + uint32_t enabled; + struct ssp_aux_config_mn mn; + struct ssp_aux_config_clk clk; + struct ssp_aux_config_tr tr_start; + struct ssp_aux_config_tr tr_stop; + struct ssp_aux_config_run run; + struct ssp_aux_config_sync sync; + struct ssp_aux_config_ext ext; + struct ssp_aux_config_link link; +}; + +struct ssp_aux_blob { + uint32_t size; + uint8_t aux_blob[256]; +}; /* structs for gathering the ssp parameters from topology */ struct ssp_config_hw { @@ -43,6 +127,7 @@ struct ssp_config_dai { uint32_t bclk_delay; uint8_t direction; struct ssp_config_hw hw_cfg[SSP_MAX_HW_CONFIG]; + struct ssp_config_aux aux_cfg[SSP_MAX_HW_CONFIG]; }; struct intel_ssp_params { @@ -54,8 +139,20 @@ struct intel_ssp_params { /* ssp vendor blob structs */ struct ssp_intel_config_data ssp_blob[SSP_MAX_DAIS][SSP_MAX_HW_CONFIG]; + struct ssp_aux_blob ssp_blob_ext[SSP_MAX_DAIS][SSP_MAX_HW_CONFIG]; }; +#define SSP_MN_DIVIDER_CONTROLS 0 +#define SSP_DMA_CLK_CONTROLS 1 +#define SSP_DMA_TRANSMISSION_START 2 +#define SSP_DMA_TRANSMISSION_STOP 3 +#define SSP_DMA_ALWAYS_RUNNING_MODE 4 +#define SSP_DMA_SYNC_DATA 5 +#define SSP_DMA_CLK_CONTROLS_EXT 6 +#define SSP_LINK_CLK_SOURCE 7 +/* officially "undefined" node for topology parsing */ +#define SSP_DMA_SYNC_NODE 32 + #define SSP_CLOCK_XTAL_OSCILLATOR 0x0 #define SSP_CLOCK_AUDIO_CARDINAL 0x1 #define SSP_CLOCK_PLL_FIXED 0x2 diff --git a/topology/nhlt/intel/ssp/ssp-process.c b/topology/nhlt/intel/ssp/ssp-process.c index 657b9d9..cebb5b5 100644 --- a/topology/nhlt/intel/ssp/ssp-process.c +++ b/topology/nhlt/intel/ssp/ssp-process.c @@ -511,6 +511,186 @@ static int ssp_calculate_intern(struct intel_nhlt_params *nhlt, int hwi) return 0; } +static int ssp_calculate_intern_ext(struct intel_nhlt_params *nhlt, int hwi) +{ + size_t aux_size, mn_size, clk_size, tr_size, run_size, sync_size, node_size, ext_size, + link_size, size, total_size; + struct intel_ssp_params *ssp; + struct ssp_config_aux *aux; + struct ssp_intel_aux_tlv *tlv; + struct ssp_intel_mn_ctl *mn; + struct ssp_intel_clk_ctl *clk; + struct ssp_intel_tr_ctl *tr; + struct ssp_intel_run_ctl *run; + struct ssp_intel_sync_ctl *sync; + struct ssp_intel_node_ctl *node; + struct ssp_intel_ext_ctl *ext; + struct ssp_intel_link_ctl *link; + uint8_t *aux_blob; + uint32_t enabled; + int di, i; + + aux_size = sizeof(struct ssp_intel_aux_tlv); + mn_size = sizeof(struct ssp_intel_mn_ctl); + clk_size = sizeof(struct ssp_intel_clk_ctl); + tr_size = sizeof(struct ssp_intel_tr_ctl); + run_size = sizeof(struct ssp_intel_run_ctl); + sync_size = sizeof(struct ssp_intel_sync_ctl); + node_size = sizeof(struct ssp_intel_node_ctl); + ext_size = sizeof(struct ssp_intel_ext_ctl); + link_size = sizeof(struct ssp_intel_link_ctl); + + ssp = (struct intel_ssp_params *)nhlt->ssp_params; + di = ssp->ssp_count; + enabled = ssp->ssp_prm[di].aux_cfg[hwi].enabled; + aux = &(ssp->ssp_prm[di].aux_cfg[hwi]); + aux_blob = ssp->ssp_blob_ext[di][hwi].aux_blob; + total_size = 0; + size = 0; + + if (enabled & BIT(SSP_MN_DIVIDER_CONTROLS)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + mn = (struct ssp_intel_mn_ctl *)(aux_blob + aux_size); + size = mn_size + aux_size; + tlv->type = SSP_MN_DIVIDER_CONTROLS; + tlv->size = mn_size; + mn->div_m = aux->mn.m_div; + mn->div_n = aux->mn.n_div; + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_DMA_CLK_CONTROLS)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + clk = (struct ssp_intel_clk_ctl *)(aux_blob + aux_size); + size = clk_size + aux_size; + tlv->type = SSP_DMA_CLK_CONTROLS; + tlv->size = clk_size; + clk->start |= SET_BITS(15, 0, aux->clk.clock_warm_up); + clk->start |= SET_BIT(16, aux->clk.mclk); + clk->start |= SET_BIT(17, aux->clk.warm_up_ovr); + clk->stop |= SET_BITS(15, 0, aux->clk.clock_stop_delay); + clk->stop |= SET_BIT(16, aux->clk.keep_running); + clk->stop |= SET_BIT(17, aux->clk.clock_stop_ovr); + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_DMA_TRANSMISSION_START)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size); + size = tr_size + aux_size; + tlv->type = SSP_DMA_TRANSMISSION_START; + tlv->size = tr_size; + tr->sampling_frequency = aux->tr_start.sampling_frequency; + tr->bit_depth = aux->tr_start.bit_depth; + tr->channel_map = aux->tr_start.channel_map; + tr->channel_config = aux->tr_start.channel_config; + tr->interleaving_style = aux->tr_start.interleaving_style; + tr->format |= SET_BITS(7, 0, aux->tr_start.number_of_channels); + tr->format |= SET_BITS(15, 8, aux->tr_start.valid_bit_depth); + tr->format |= SET_BITS(23, 16, aux->tr_start.sample_type); + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_DMA_TRANSMISSION_STOP)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size); + size = tr_size + aux_size; + tlv->type = SSP_DMA_TRANSMISSION_STOP; + tlv->size = tr_size; + tr->sampling_frequency = aux->tr_stop.sampling_frequency; + tr->bit_depth = aux->tr_stop.bit_depth; + tr->channel_map = aux->tr_stop.channel_map; + tr->channel_config = aux->tr_stop.channel_config; + tr->interleaving_style = aux->tr_stop.interleaving_style; + tr->format |= SET_BITS(7, 0, aux->tr_stop.number_of_channels); + tr->format |= SET_BITS(15, 8, aux->tr_stop.valid_bit_depth); + tr->format |= SET_BITS(23, 16, aux->tr_stop.sample_type); + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_DMA_ALWAYS_RUNNING_MODE)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + run = (struct ssp_intel_run_ctl *)(aux_blob + aux_size); + size = run_size + aux_size; + tlv->type = SSP_DMA_ALWAYS_RUNNING_MODE; + tlv->size = run_size; + run->enabled = aux->run.always_run; + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_DMA_SYNC_DATA)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + sync = (struct ssp_intel_sync_ctl *)(aux_blob + aux_size); + size = sync_size + aux_size; + tlv->type = SSP_DMA_SYNC_DATA; + tlv->size = sync_size; + sync->sync_denominator = aux->sync.sync_denominator; + sync->count = aux->sync.count; + aux_blob += size; + total_size += size; + for (i = 0; i < sync->count; i++) { + node = (struct ssp_intel_node_ctl *)(aux_blob); + size = node_size; + node->node_id = aux->sync.nodes[i].node_id; + node->sampling_rate = aux->sync.nodes[i].sampling_rate; + tlv->size += node_size; + aux_blob += size; + total_size += size; + } + } + + if (enabled & BIT(SSP_DMA_CLK_CONTROLS_EXT)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + ext = (struct ssp_intel_ext_ctl *)(aux_blob + aux_size); + size = ext_size + aux_size; + tlv->type = SSP_DMA_CLK_CONTROLS_EXT; + tlv->size = ext_size; + ext->ext_data |= SET_BIT(0, aux->ext.mclk_policy_override); + ext->ext_data |= SET_BIT(1, aux->ext.mclk_always_running); + ext->ext_data |= SET_BIT(2, aux->ext.mclk_starts_on_gtw_init); + ext->ext_data |= SET_BIT(3, aux->ext.mclk_starts_on_run); + ext->ext_data |= SET_BIT(4, aux->ext.mclk_starts_on_pause); + ext->ext_data |= SET_BIT(5, aux->ext.mclk_stops_on_pause); + ext->ext_data |= SET_BIT(6, aux->ext.mclk_stops_on_reset); + ext->ext_data |= SET_BIT(8, aux->ext.bclk_policy_override); + ext->ext_data |= SET_BIT(9, aux->ext.bclk_always_running); + ext->ext_data |= SET_BIT(10, aux->ext.bclk_starts_on_gtw_init); + ext->ext_data |= SET_BIT(11, aux->ext.bclk_starts_on_run); + ext->ext_data |= SET_BIT(12, aux->ext.bclk_starts_on_pause); + ext->ext_data |= SET_BIT(13, aux->ext.bclk_stops_on_pause); + ext->ext_data |= SET_BIT(14, aux->ext.bclk_stops_on_reset); + ext->ext_data |= SET_BIT(16, aux->ext.sync_policy_override); + ext->ext_data |= SET_BIT(17, aux->ext.sync_always_running); + ext->ext_data |= SET_BIT(18, aux->ext.sync_starts_on_gtw_init); + ext->ext_data |= SET_BIT(19, aux->ext.sync_starts_on_run); + ext->ext_data |= SET_BIT(20, aux->ext.sync_starts_on_pause); + ext->ext_data |= SET_BIT(21, aux->ext.sync_stops_on_pause); + ext->ext_data |= SET_BIT(22, aux->ext.sync_stops_on_reset); + aux_blob += size; + total_size += size; + } + + if (enabled & BIT(SSP_LINK_CLK_SOURCE)) { + tlv = (struct ssp_intel_aux_tlv *)aux_blob; + link = (struct ssp_intel_link_ctl *)(aux_blob + aux_size); + size = link_size + aux_size; + tlv->type = SSP_LINK_CLK_SOURCE; + tlv->size = link_size; + link->clock_source = aux->link.clock_source; + aux_blob += size; + total_size += size; + } + + ssp->ssp_blob_ext[di][hwi].size = total_size; + + return 0; +} + int ssp_calculate(struct intel_nhlt_params *nhlt) { struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; @@ -520,9 +700,12 @@ int ssp_calculate(struct intel_nhlt_params *nhlt) return -EINVAL; /* calculate blob for every hw config */ - for (i = 0; i < ssp->ssp_hw_config_count[ssp->ssp_count]; i++) + for (i = 0; i < ssp->ssp_hw_config_count[ssp->ssp_count]; i++) { if (ssp_calculate_intern(nhlt, i) < 0) return -EINVAL; + if (ssp_calculate_intern_ext(nhlt, i) < 0) + return -EINVAL; + } ssp_print_internal(ssp); ssp_print_calculated(ssp); @@ -579,9 +762,13 @@ int ssp_get_hw_params(struct intel_nhlt_params *nhlt, int dai_index, int hw_inde * Supposed to be called after all ssp DAIs are parsed from topology and the final nhlt blob is * generated. */ -int ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, size_t *size) +int ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, int dai_index, + int hw_config_index, size_t *size) { - *size = sizeof(struct ssp_intel_config_data); + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + + *size = sizeof(struct ssp_intel_config_data) + + ssp->ssp_blob_ext[dai_index][hw_config_index].size; return 0; } @@ -609,6 +796,11 @@ int ssp_get_vendor_blob(struct intel_nhlt_params *nhlt, uint8_t *vendor_blob, memcpy(vendor_blob, &ssp->ssp_blob[dai_index][hw_config_index], sizeof(struct ssp_intel_config_data)); + /* ext data */ + memcpy(vendor_blob + sizeof(struct ssp_intel_config_data), + ssp->ssp_blob_ext[dai_index][hw_config_index].aux_blob, + ssp->ssp_blob_ext[dai_index][hw_config_index].size); + return 0; } @@ -726,11 +918,224 @@ int ssp_hw_set_params(struct intel_nhlt_params *nhlt, const char *format, const return 0; } +int ssp_mn_set_params(struct intel_nhlt_params *nhlt, int m_div, int n_div) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_MN_DIVIDER_CONTROLS); + + ssp->ssp_prm[di].aux_cfg[hwi].mn.m_div = m_div; + ssp->ssp_prm[di].aux_cfg[hwi].mn.n_div = n_div; + + return 0; +} + +int ssp_clk_set_params(struct intel_nhlt_params *nhlt, int clock_warm_up, int mclk, int warm_up_ovr, + int clock_stop_delay, int keep_running, int clock_stop_ovr) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS); + + ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_warm_up = clock_warm_up; + ssp->ssp_prm[di].aux_cfg[hwi].clk.mclk = mclk; + ssp->ssp_prm[di].aux_cfg[hwi].clk.warm_up_ovr = warm_up_ovr; + ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_delay = clock_stop_delay; + ssp->ssp_prm[di].aux_cfg[hwi].clk.keep_running = keep_running; + ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_ovr = clock_stop_ovr; + + return 0; +} + +int ssp_tr_start_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, + int bit_depth, int channel_map, int channel_config, + int interleaving_style, int number_of_channels, + int valid_bit_depth, int sample_type) +{ + struct intel_ssp_params *ssp; + struct ssp_aux_config_tr *tr; + int di, hwi; + + ssp = (struct intel_ssp_params *)nhlt->ssp_params; + di = ssp->ssp_count; + hwi = ssp->ssp_hw_config_count[di]; + if (di < 0 || hwi < 0) + return -EINVAL; + tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_start); + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_START); + + tr->sampling_frequency = sampling_frequency; + tr->bit_depth = bit_depth; + tr->channel_map = channel_map; + tr->channel_config = channel_config; + tr->interleaving_style = interleaving_style; + tr->number_of_channels = number_of_channels; + tr->valid_bit_depth = valid_bit_depth; + tr->sample_type = sample_type; + + return 0; +} + +int ssp_tr_stop_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, + int bit_depth, int channel_map, int channel_config, + int interleaving_style, int number_of_channels, + int valid_bit_depth, int sample_type) +{ + struct intel_ssp_params *ssp; + struct ssp_aux_config_tr *tr; + int di, hwi; + + ssp = (struct intel_ssp_params *)nhlt->ssp_params; + di = ssp->ssp_count; + hwi = ssp->ssp_hw_config_count[di]; + if (di < 0 || hwi < 0) + return -EINVAL; + tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_stop); + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_STOP); + + tr->sampling_frequency = sampling_frequency; + tr->bit_depth = bit_depth; + tr->channel_map = channel_map; + tr->channel_config = channel_config; + tr->interleaving_style = interleaving_style; + tr->number_of_channels = number_of_channels; + tr->valid_bit_depth = valid_bit_depth; + tr->sample_type = sample_type; + + return 0; +} + +int ssp_run_set_params(struct intel_nhlt_params *nhlt, int always_run) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_ALWAYS_RUNNING_MODE); + + ssp->ssp_prm[di].aux_cfg[hwi].run.always_run = always_run; + + return 0; +} + +int ssp_sync_set_params(struct intel_nhlt_params *nhlt, int sync_denominator) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_SYNC_DATA); + + ssp->ssp_prm[di].aux_cfg[hwi].sync.sync_denominator = sync_denominator; + + return 0; +} + +int ssp_node_set_params(struct intel_nhlt_params *nhlt, int node_id, int sampling_rate) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + int count; + + if (di < 0 || hwi < 0) + return -EINVAL; + + count = ssp->ssp_prm[di].aux_cfg[hwi].sync.count; + if (count > SSP_MAX_DAIS) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].node_id = node_id; + ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].sampling_rate = sampling_rate; + + ssp->ssp_prm[di].aux_cfg[hwi].sync.count++; + + return 0; +} + +int ssp_ext_set_params(struct intel_nhlt_params *nhlt, int mclk_policy_override, + int mclk_always_running, int mclk_starts_on_gtw_init, int mclk_starts_on_run, + int mclk_starts_on_pause, int mclk_stops_on_pause, int mclk_stops_on_reset, + int bclk_policy_override, int bclk_always_running, + int bclk_starts_on_gtw_init, int bclk_starts_on_run, + int bclk_starts_on_pause, int bclk_stops_on_pause, int bclk_stops_on_reset, + int sync_policy_override, int sync_always_running, + int sync_starts_on_gtw_init, int sync_starts_on_run, + int sync_starts_on_pause, int sync_stops_on_pause, int sync_stops_on_reset) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS_EXT); + + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_policy_override = mclk_policy_override; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_always_running = mclk_always_running; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_gtw_init = mclk_starts_on_gtw_init; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_run = mclk_starts_on_run; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_pause = mclk_starts_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_pause = mclk_stops_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_reset = mclk_stops_on_reset; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_policy_override = bclk_policy_override; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_always_running = bclk_always_running; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_gtw_init = bclk_starts_on_gtw_init; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_run = bclk_starts_on_run; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_pause = bclk_starts_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_pause = bclk_stops_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_reset = bclk_stops_on_reset; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_policy_override = sync_policy_override; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_always_running = sync_always_running; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_gtw_init = sync_starts_on_gtw_init; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_run = sync_starts_on_run; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_pause = sync_starts_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_pause = sync_stops_on_pause; + ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_reset = sync_stops_on_reset; + + return 0; +} + +int ssp_link_set_params(struct intel_nhlt_params *nhlt, int clock_source) +{ + struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; + int di = ssp->ssp_count; + int hwi = ssp->ssp_hw_config_count[di]; + + if (di < 0 || hwi < 0) + return -EINVAL; + + ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_LINK_CLK_SOURCE); + + ssp->ssp_prm[di].aux_cfg[hwi].link.clock_source = clock_source; + + return 0; +} + /* init ssp parameters, should be called before parsing dais */ int ssp_init_params(struct intel_nhlt_params *nhlt) { struct intel_ssp_params *ssp; - int i; + int i, j; ssp = calloc(1, sizeof(struct intel_ssp_params)); if (!ssp) @@ -739,8 +1144,11 @@ int ssp_init_params(struct intel_nhlt_params *nhlt) nhlt->ssp_params = ssp; ssp->ssp_count = 0; - for (i = 0; i < SSP_MAX_DAIS; i++) + for (i = 0; i < SSP_MAX_DAIS; i++) { ssp->ssp_hw_config_count[i] = 0; + for (j = 0; j < SSP_MAX_HW_CONFIG; j++) + ssp->ssp_prm[i].aux_cfg[j].sync.count = 0; + } return 0; } diff --git a/topology/nhlt/intel/ssp/ssp-process.h b/topology/nhlt/intel/ssp/ssp-process.h index 1226b76..e59b50a 100644 --- a/topology/nhlt/intel/ssp/ssp-process.h +++ b/topology/nhlt/intel/ssp/ssp-process.h @@ -24,6 +24,32 @@ int ssp_hw_set_params(struct intel_nhlt_params *nhlt, const char *format, const const char *fsync_invert, int mclk_freq, int bclk_freq, int fsync_freq, int tdm_slots, int tdm_slot_width, int tx_slots, int rx_slots); +/* set aux params when parsing topology2 conf */ +int ssp_mn_set_params(struct intel_nhlt_params *nhlt, int m_div, int n_div); +int ssp_clk_set_params(struct intel_nhlt_params *nhlt, int clock_warm_up, int mclk, int warm_up_ovr, + int clock_stop_delay, int keep_running, int clock_stop_ovr); +int ssp_tr_start_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, + int bit_depth, int channel_map, int hannel_config, + int interleaving_style, int number_of_channels, + int valid_bit_depth, int sample_type); +int ssp_tr_stop_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, + int bit_depth, int channel_map, int hannel_config, + int interleaving_style, int number_of_channels, + int valid_bit_depth, int sample_type); +int ssp_run_set_params(struct intel_nhlt_params *nhlt, int always_run); +int ssp_sync_set_params(struct intel_nhlt_params *nhlt, int sync_denominator); +int ssp_node_set_params(struct intel_nhlt_params *nhlt, int node_id, int sampling_rate); +int ssp_ext_set_params(struct intel_nhlt_params *nhlt, int mclk_policy_override, + int mclk_always_running, int mclk_starts_on_gtw_init, int mclk_starts_on_run, + int mclk_starts_on_pause, int mclk_stops_on_pause, int mclk_stops_on_reset, + int bclk_policy_override, int bclk_always_running, + int bclk_starts_on_gtw_init, int bclk_starts_on_run, + int bclk_starts_on_pause, int bclk_stops_on_pause, int bclk_stops_on_reset, + int sync_policy_override, int sync_always_running, + int sync_starts_on_gtw_init, int sync_starts_on_run, + int sync_starts_on_pause, int sync_stops_on_pause, int sync_stops_on_reset); +int ssp_link_set_params(struct intel_nhlt_params *nhlt, int clock_source); + /* calculate the blob after parsing the values*/ int ssp_calculate(struct intel_nhlt_params *nhlt); /* get spec parameters when building the nhlt endpoint */ @@ -34,7 +60,8 @@ int ssp_get_hw_params(struct intel_nhlt_params *nhlt, int dai_index, int hw_inde int ssp_get_dir(struct intel_nhlt_params *nhlt, int dai_index, uint8_t *dir); /* get vendor specific blob when building the nhlt endpoint */ int ssp_get_vendor_blob_count(struct intel_nhlt_params *nhlt); -int ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, size_t *size); +int ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, int dai_index, int hw_config_index, + size_t *size); int ssp_get_vendor_blob(struct intel_nhlt_params *nhlt, uint8_t *vendor_blob, int dai_index, int hw_config_index);