summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--topology/nhlt/intel/ssp-nhlt.c385
-rw-r--r--topology/nhlt/intel/ssp/ssp-debug.c128
-rw-r--r--topology/nhlt/intel/ssp/ssp-intel.h47
-rw-r--r--topology/nhlt/intel/ssp/ssp-internal.h97
-rw-r--r--topology/nhlt/intel/ssp/ssp-process.c418
-rw-r--r--topology/nhlt/intel/ssp/ssp-process.h29
6 files changed, 1066 insertions, 38 deletions
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 <stdio.h>
#include <stdint.h>
#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);