1c72fcc34Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause 2c72fcc34Sopenharmony_ci// 3c72fcc34Sopenharmony_ci// Copyright(c) 2021 Intel Corporation. All rights reserved. 4c72fcc34Sopenharmony_ci// 5c72fcc34Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 6c72fcc34Sopenharmony_ci// Keyon Jie <yang.jie@linux.intel.com> 7c72fcc34Sopenharmony_ci// Rander Wang <rander.wang@linux.intel.com> 8c72fcc34Sopenharmony_ci// Jaska Uimonen <jaska.uimonen@linux.intel.com> 9c72fcc34Sopenharmony_ci 10c72fcc34Sopenharmony_ci#include "aconfig.h" 11c72fcc34Sopenharmony_ci#include <stdint.h> 12c72fcc34Sopenharmony_ci#include <errno.h> 13c72fcc34Sopenharmony_ci#include <stdio.h> 14c72fcc34Sopenharmony_ci#include <stdlib.h> 15c72fcc34Sopenharmony_ci#include <string.h> 16c72fcc34Sopenharmony_ci#include <stdbool.h> 17c72fcc34Sopenharmony_ci#include <alsa/global.h> 18c72fcc34Sopenharmony_ci#include <alsa/input.h> 19c72fcc34Sopenharmony_ci#include <alsa/output.h> 20c72fcc34Sopenharmony_ci#include <alsa/conf.h> 21c72fcc34Sopenharmony_ci#include <alsa/error.h> 22c72fcc34Sopenharmony_ci#include "../intel-nhlt.h" 23c72fcc34Sopenharmony_ci#include "../../nhlt.h" 24c72fcc34Sopenharmony_ci#include "ssp-process.h" 25c72fcc34Sopenharmony_ci#include "ssp-intel.h" 26c72fcc34Sopenharmony_ci#include "ssp-internal.h" 27c72fcc34Sopenharmony_ci#include "ssp-debug.h" 28c72fcc34Sopenharmony_ci 29c72fcc34Sopenharmony_cistatic int popcount(uint32_t value) 30c72fcc34Sopenharmony_ci{ 31c72fcc34Sopenharmony_ci int bits_set = 0; 32c72fcc34Sopenharmony_ci 33c72fcc34Sopenharmony_ci while (value) { 34c72fcc34Sopenharmony_ci bits_set += value & 1; 35c72fcc34Sopenharmony_ci value >>= 1; 36c72fcc34Sopenharmony_ci } 37c72fcc34Sopenharmony_ci 38c72fcc34Sopenharmony_ci return bits_set; 39c72fcc34Sopenharmony_ci} 40c72fcc34Sopenharmony_ci 41c72fcc34Sopenharmony_cistatic void ssp_calculate_intern_v15(struct intel_nhlt_params *nhlt, int hwi) 42c72fcc34Sopenharmony_ci{ 43c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 44c72fcc34Sopenharmony_ci int di = ssp->ssp_count;; 45c72fcc34Sopenharmony_ci struct ssp_intel_config_data_1_5 *blob15 = &ssp->ssp_blob_1_5[di][hwi]; 46c72fcc34Sopenharmony_ci struct ssp_intel_config_data *blob = &ssp->ssp_blob[di][hwi]; 47c72fcc34Sopenharmony_ci int i; 48c72fcc34Sopenharmony_ci 49c72fcc34Sopenharmony_ci blob15->gateway_attributes = ssp->ssp_blob[di][hwi].gateway_attributes; 50c72fcc34Sopenharmony_ci blob15->version = SSP_BLOB_VER_1_5; 51c72fcc34Sopenharmony_ci 52c72fcc34Sopenharmony_ci for (i = 0; i < 8; i++) 53c72fcc34Sopenharmony_ci blob15->ts_group[i] = blob->ts_group[i]; 54c72fcc34Sopenharmony_ci 55c72fcc34Sopenharmony_ci blob15->ssc0 = blob->ssc0; 56c72fcc34Sopenharmony_ci blob15->ssc1 = blob->ssc1; 57c72fcc34Sopenharmony_ci blob15->sscto = blob->sscto; 58c72fcc34Sopenharmony_ci blob15->sspsp = blob->sspsp; 59c72fcc34Sopenharmony_ci blob15->sstsa = blob->sstsa; 60c72fcc34Sopenharmony_ci blob15->ssrsa = blob->ssrsa; 61c72fcc34Sopenharmony_ci blob15->ssc2 = blob->ssc2; 62c72fcc34Sopenharmony_ci blob15->sspsp2 = blob->sspsp2; 63c72fcc34Sopenharmony_ci blob15->ssc3 = blob->ssc3; 64c72fcc34Sopenharmony_ci blob15->ssioc = blob->ssioc; 65c72fcc34Sopenharmony_ci 66c72fcc34Sopenharmony_ci /* for now we use only 1 divider as in legacy */ 67c72fcc34Sopenharmony_ci blob15->mdivctlr = blob->mdivc; 68c72fcc34Sopenharmony_ci ssp->ssp_prm[di].mdivr[hwi].count = 1; 69c72fcc34Sopenharmony_ci blob15->mdivrcnt = ssp->ssp_prm[di].mdivr[hwi].count; 70c72fcc34Sopenharmony_ci ssp->ssp_prm[di].mdivr[hwi].mdivrs[0] = blob->mdivr; 71c72fcc34Sopenharmony_ci 72c72fcc34Sopenharmony_ci blob15->size = sizeof(struct ssp_intel_config_data_1_5) + 73c72fcc34Sopenharmony_ci blob15->mdivrcnt * sizeof(uint32_t) + 74c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[di][hwi].size; 75c72fcc34Sopenharmony_ci} 76c72fcc34Sopenharmony_ci 77c72fcc34Sopenharmony_cistatic int ssp_calculate_intern(struct intel_nhlt_params *nhlt, int hwi) 78c72fcc34Sopenharmony_ci{ 79c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 80c72fcc34Sopenharmony_ci uint32_t active_tx_slots = 2; 81c72fcc34Sopenharmony_ci uint32_t active_rx_slots = 2; 82c72fcc34Sopenharmony_ci uint32_t inverted_frame = 0; 83c72fcc34Sopenharmony_ci uint32_t inverted_bclk = 0; 84c72fcc34Sopenharmony_ci uint32_t frame_end_padding; 85c72fcc34Sopenharmony_ci uint32_t total_sample_size; 86c72fcc34Sopenharmony_ci uint32_t slot_end_padding; 87c72fcc34Sopenharmony_ci bool start_delay = false; 88c72fcc34Sopenharmony_ci uint32_t frame_len = 0; 89c72fcc34Sopenharmony_ci uint32_t sample_width; 90c72fcc34Sopenharmony_ci uint32_t end_padding; 91c72fcc34Sopenharmony_ci uint32_t data_size; 92c72fcc34Sopenharmony_ci uint32_t bdiv_min; 93c72fcc34Sopenharmony_ci bool cfs = false; 94c72fcc34Sopenharmony_ci uint32_t clk_div; 95c72fcc34Sopenharmony_ci uint32_t bdiv; 96c72fcc34Sopenharmony_ci uint32_t tft; 97c72fcc34Sopenharmony_ci uint32_t rft; 98c72fcc34Sopenharmony_ci int di; 99c72fcc34Sopenharmony_ci unsigned int i, j; 100c72fcc34Sopenharmony_ci 101c72fcc34Sopenharmony_ci if (!ssp) 102c72fcc34Sopenharmony_ci return -EINVAL; 103c72fcc34Sopenharmony_ci 104c72fcc34Sopenharmony_ci di = ssp->ssp_count; 105c72fcc34Sopenharmony_ci 106c72fcc34Sopenharmony_ci /* should be eventually the lp_mode defined in pipeline */ 107c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].gateway_attributes = 0; 108c72fcc34Sopenharmony_ci 109c72fcc34Sopenharmony_ci for (j = 0; j < SSP_TDM_MAX_SLOT_MAP_COUNT; j++) { 110c72fcc34Sopenharmony_ci for (i = 0; i < ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots; i++) 111c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ts_group[j] |= (i << (i * 4)); 112c72fcc34Sopenharmony_ci for (; i < SSP_TDM_MAX_SLOT_MAP_COUNT; i++) 113c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ts_group[j] |= (0xF << (i * 4)); 114c72fcc34Sopenharmony_ci } 115c72fcc34Sopenharmony_ci 116c72fcc34Sopenharmony_ci /* reset SSP settings */ 117c72fcc34Sopenharmony_ci /* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */ 118c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM; 119c72fcc34Sopenharmony_ci 120c72fcc34Sopenharmony_ci /* sscr1 dynamic settings are SFRMDIR, SCLKDIR, SCFR */ 121c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_TRAIL | SSCR1_RSRE | 122c72fcc34Sopenharmony_ci SSCR1_TSRE; 123c72fcc34Sopenharmony_ci 124c72fcc34Sopenharmony_ci /* sscr2 dynamic setting is LJDFD */ 125c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 = SSCR2_SDFD | SSCR2_TURM1; 126c72fcc34Sopenharmony_ci 127c72fcc34Sopenharmony_ci /* sscr3 dynamic settings are TFT, RFT */ 128c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc3 = 0; 129c72fcc34Sopenharmony_ci 130c72fcc34Sopenharmony_ci /* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */ 131c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp = 0; 132c72fcc34Sopenharmony_ci 133c72fcc34Sopenharmony_ci /* sspsp2 no dynamic setting */ 134c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp2 = 0x0; 135c72fcc34Sopenharmony_ci 136c72fcc34Sopenharmony_ci /* ssioc dynamic setting is SFCR */ 137c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssioc = SSIOC_SCOE; 138c72fcc34Sopenharmony_ci 139c72fcc34Sopenharmony_ci /* ssto no dynamic setting */ 140c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sscto = 0x0; 141c72fcc34Sopenharmony_ci 142c72fcc34Sopenharmony_ci /* sstsa dynamic setting is TTSA, default 2 slots */ 143c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sstsa = SSTSA_SSTSA(ssp->ssp_prm[di].hw_cfg[hwi].tx_slots); 144c72fcc34Sopenharmony_ci 145c72fcc34Sopenharmony_ci /* ssrsa dynamic setting is RTSA, default 2 slots */ 146c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssrsa = SSRSA_SSRSA(ssp->ssp_prm[di].hw_cfg[hwi].rx_slots); 147c72fcc34Sopenharmony_ci 148c72fcc34Sopenharmony_ci switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_CLOCK_PROVIDER_MASK) { 149c72fcc34Sopenharmony_ci case SSP_FMT_CBP_CFP: 150c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; 151c72fcc34Sopenharmony_ci break; 152c72fcc34Sopenharmony_ci case SSP_FMT_CBC_CFC: 153c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCFR; 154c72fcc34Sopenharmony_ci cfs = true; 155c72fcc34Sopenharmony_ci break; 156c72fcc34Sopenharmony_ci case SSP_FMT_CBP_CFC: 157c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCLKDIR; 158c72fcc34Sopenharmony_ci /* FIXME: this mode has not been tested */ 159c72fcc34Sopenharmony_ci 160c72fcc34Sopenharmony_ci cfs = true; 161c72fcc34Sopenharmony_ci break; 162c72fcc34Sopenharmony_ci case SSP_FMT_CBC_CFP: 163c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= SSCR1_SCFR | SSCR1_SFRMDIR; 164c72fcc34Sopenharmony_ci /* FIXME: this mode has not been tested */ 165c72fcc34Sopenharmony_ci break; 166c72fcc34Sopenharmony_ci default: 167c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): format & PROVIDER_MASK EINVAL\n"); 168c72fcc34Sopenharmony_ci return -EINVAL; 169c72fcc34Sopenharmony_ci } 170c72fcc34Sopenharmony_ci 171c72fcc34Sopenharmony_ci /* clock signal polarity */ 172c72fcc34Sopenharmony_ci switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_INV_MASK) { 173c72fcc34Sopenharmony_ci case SSP_FMT_NB_NF: 174c72fcc34Sopenharmony_ci break; 175c72fcc34Sopenharmony_ci case SSP_FMT_NB_IF: 176c72fcc34Sopenharmony_ci inverted_frame = 1; /* handled later with format */ 177c72fcc34Sopenharmony_ci break; 178c72fcc34Sopenharmony_ci case SSP_FMT_IB_IF: 179c72fcc34Sopenharmony_ci inverted_bclk = 1; /* handled later with bclk idle */ 180c72fcc34Sopenharmony_ci inverted_frame = 1; /* handled later with format */ 181c72fcc34Sopenharmony_ci break; 182c72fcc34Sopenharmony_ci case SSP_FMT_IB_NF: 183c72fcc34Sopenharmony_ci inverted_bclk = 1; /* handled later with bclk idle */ 184c72fcc34Sopenharmony_ci break; 185c72fcc34Sopenharmony_ci default: 186c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate: format & INV_MASK EINVAL\n"); 187c72fcc34Sopenharmony_ci return -EINVAL; 188c72fcc34Sopenharmony_ci } 189c72fcc34Sopenharmony_ci 190c72fcc34Sopenharmony_ci /* supporting bclk idle state */ 191c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].clks_control & 192c72fcc34Sopenharmony_ci SSP_INTEL_CLKCTRL_BCLK_IDLE_HIGH) { 193c72fcc34Sopenharmony_ci /* bclk idle state high */ 194c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SCMODE((inverted_bclk ^ 0x3) & 0x3); 195c72fcc34Sopenharmony_ci } else { 196c72fcc34Sopenharmony_ci /* bclk idle state low */ 197c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SCMODE(inverted_bclk); 198c72fcc34Sopenharmony_ci } 199c72fcc34Sopenharmony_ci 200c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_MOD | SSCR0_ACS; 201c72fcc34Sopenharmony_ci 202c72fcc34Sopenharmony_ci /* Additional hardware settings */ 203c72fcc34Sopenharmony_ci 204c72fcc34Sopenharmony_ci /* Receiver Time-out Interrupt Disabled/Enabled */ 205c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_TINTE) ? 206c72fcc34Sopenharmony_ci SSCR1_TINTE : 0; 207c72fcc34Sopenharmony_ci 208c72fcc34Sopenharmony_ci /* Peripheral Trailing Byte Interrupts Disable/Enable */ 209c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PINTE) ? 210c72fcc34Sopenharmony_ci SSCR1_PINTE : 0; 211c72fcc34Sopenharmony_ci 212c72fcc34Sopenharmony_ci /* Enable/disable internal loopback. Output of transmit serial 213c72fcc34Sopenharmony_ci * shifter connected to input of receive serial shifter, internally. 214c72fcc34Sopenharmony_ci */ 215c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc1 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_LBM) ? 216c72fcc34Sopenharmony_ci SSCR1_LBM : 0; 217c72fcc34Sopenharmony_ci 218c72fcc34Sopenharmony_ci /* Transmit data are driven at the same/opposite clock edge specified 219c72fcc34Sopenharmony_ci * in SSPSP.SCMODE[1:0] 220c72fcc34Sopenharmony_ci */ 221c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_SMTATF) ? 222c72fcc34Sopenharmony_ci SSCR2_SMTATF : 0; 223c72fcc34Sopenharmony_ci 224c72fcc34Sopenharmony_ci /* Receive data are sampled at the same/opposite clock edge specified 225c72fcc34Sopenharmony_ci * in SSPSP.SCMODE[1:0] 226c72fcc34Sopenharmony_ci */ 227c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_MMRATF) ? 228c72fcc34Sopenharmony_ci SSCR2_MMRATF : 0; 229c72fcc34Sopenharmony_ci 230c72fcc34Sopenharmony_ci /* Enable/disable the fix for PSP consumer mode TXD wait for frame 231c72fcc34Sopenharmony_ci * de-assertion before starting the second channel 232c72fcc34Sopenharmony_ci */ 233c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PSPSTWFDFD) ? 234c72fcc34Sopenharmony_ci SSCR2_PSPSTWFDFD : 0; 235c72fcc34Sopenharmony_ci 236c72fcc34Sopenharmony_ci /* Enable/disable the fix for PSP provider mode FSRT with dummy stop & 237c72fcc34Sopenharmony_ci * frame end padding capability 238c72fcc34Sopenharmony_ci */ 239c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 |= (ssp->ssp_prm[di].quirks & SSP_INTEL_QUIRK_PSPSRWFDFD) ? 240c72fcc34Sopenharmony_ci SSCR2_PSPSRWFDFD : 0; 241c72fcc34Sopenharmony_ci 242c72fcc34Sopenharmony_ci if (!ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) { 243c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): invalid MCLK = %u \n", 244c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate); 245c72fcc34Sopenharmony_ci return -EINVAL; 246c72fcc34Sopenharmony_ci } 247c72fcc34Sopenharmony_ci 248c72fcc34Sopenharmony_ci if (!ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate || 249c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate > ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) { 250c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): BCLK %u Hz = 0 or > MCLK %u Hz\n", 251c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate, 252c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate); 253c72fcc34Sopenharmony_ci return -EINVAL; 254c72fcc34Sopenharmony_ci } 255c72fcc34Sopenharmony_ci 256c72fcc34Sopenharmony_ci /* calc frame width based on BCLK and rate - must be divisible */ 257c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate % ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate) { 258c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): BCLK %u is not divisible by rate %u\n", 259c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate, 260c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate); 261c72fcc34Sopenharmony_ci return -EINVAL; 262c72fcc34Sopenharmony_ci } 263c72fcc34Sopenharmony_ci 264c72fcc34Sopenharmony_ci /* must be enough BCLKs for data */ 265c72fcc34Sopenharmony_ci bdiv = ssp->ssp_prm[di].hw_cfg[hwi].bclk_rate / ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate; 266c72fcc34Sopenharmony_ci if (bdiv < ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width * 267c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots) { 268c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): not enough BCLKs need %u\n", 269c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width * 270c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots); 271c72fcc34Sopenharmony_ci return -EINVAL; 272c72fcc34Sopenharmony_ci } 273c72fcc34Sopenharmony_ci 274c72fcc34Sopenharmony_ci /* tdm_slot_width must be <= 38 for SSP */ 275c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width > 38) { 276c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): tdm_slot_width %u > 38\n", 277c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width); 278c72fcc34Sopenharmony_ci return -EINVAL; 279c72fcc34Sopenharmony_ci } 280c72fcc34Sopenharmony_ci 281c72fcc34Sopenharmony_ci bdiv_min = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots * 282c72fcc34Sopenharmony_ci (ssp->ssp_prm[di].tdm_per_slot_padding_flag ? 283c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width : 284c72fcc34Sopenharmony_ci ssp->ssp_prm[di].sample_valid_bits); 285c72fcc34Sopenharmony_ci if (bdiv < bdiv_min) { 286c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): bdiv(%u) < bdiv_min(%u)\n", 287c72fcc34Sopenharmony_ci bdiv, bdiv_min); 288c72fcc34Sopenharmony_ci return -EINVAL; 289c72fcc34Sopenharmony_ci } 290c72fcc34Sopenharmony_ci 291c72fcc34Sopenharmony_ci frame_end_padding = bdiv - bdiv_min; 292c72fcc34Sopenharmony_ci if (frame_end_padding > SSPSP2_FEP_MASK) { 293c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): frame_end_padding too big: %u\n", 294c72fcc34Sopenharmony_ci frame_end_padding); 295c72fcc34Sopenharmony_ci return -EINVAL; 296c72fcc34Sopenharmony_ci } 297c72fcc34Sopenharmony_ci 298c72fcc34Sopenharmony_ci /* format */ 299c72fcc34Sopenharmony_ci switch (ssp->ssp_prm[di].hw_cfg[hwi].format & SSP_FMT_FORMAT_MASK) { 300c72fcc34Sopenharmony_ci case SSP_FMT_I2S: 301c72fcc34Sopenharmony_ci 302c72fcc34Sopenharmony_ci start_delay = true; 303c72fcc34Sopenharmony_ci 304c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots); 305c72fcc34Sopenharmony_ci 306c72fcc34Sopenharmony_ci if (bdiv % 2) { 307c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): bdiv %u is not divisible by 2\n", 308c72fcc34Sopenharmony_ci bdiv); 309c72fcc34Sopenharmony_ci return -EINVAL; 310c72fcc34Sopenharmony_ci } 311c72fcc34Sopenharmony_ci 312c72fcc34Sopenharmony_ci /* set asserted frame length to half frame length */ 313c72fcc34Sopenharmony_ci frame_len = bdiv / 2; 314c72fcc34Sopenharmony_ci 315c72fcc34Sopenharmony_ci /* 316c72fcc34Sopenharmony_ci * handle frame polarity, I2S default is falling/active low, 317c72fcc34Sopenharmony_ci * non-inverted(inverted_frame=0) -- active low(SFRMP=0), 318c72fcc34Sopenharmony_ci * inverted(inverted_frame=1) -- rising/active high(SFRMP=1), 319c72fcc34Sopenharmony_ci * so, we should set SFRMP to inverted_frame. 320c72fcc34Sopenharmony_ci */ 321c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(inverted_frame); 322c72fcc34Sopenharmony_ci 323c72fcc34Sopenharmony_ci /* 324c72fcc34Sopenharmony_ci * for I2S/LEFT_J, the padding has to happen at the end 325c72fcc34Sopenharmony_ci * of each slot 326c72fcc34Sopenharmony_ci */ 327c72fcc34Sopenharmony_ci if (frame_end_padding % 2) { 328c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate():frame_end_padding %u not divisible by 2\n", 329c72fcc34Sopenharmony_ci frame_end_padding); 330c72fcc34Sopenharmony_ci return -EINVAL; 331c72fcc34Sopenharmony_ci } 332c72fcc34Sopenharmony_ci 333c72fcc34Sopenharmony_ci slot_end_padding = frame_end_padding / 2; 334c72fcc34Sopenharmony_ci 335c72fcc34Sopenharmony_ci if (slot_end_padding > SSP_INTEL_SLOT_PADDING_MAX) { 336c72fcc34Sopenharmony_ci /* too big padding */ 337c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): slot_end_padding > %d\n", 338c72fcc34Sopenharmony_ci SSP_INTEL_SLOT_PADDING_MAX); 339c72fcc34Sopenharmony_ci return -EINVAL; 340c72fcc34Sopenharmony_ci } 341c72fcc34Sopenharmony_ci 342c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding); 343c72fcc34Sopenharmony_ci slot_end_padding >>= SSPSP_DMYSTOP_BITS; 344c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding); 345c72fcc34Sopenharmony_ci 346c72fcc34Sopenharmony_ci break; 347c72fcc34Sopenharmony_ci 348c72fcc34Sopenharmony_ci case SSP_FMT_LEFT_J: 349c72fcc34Sopenharmony_ci 350c72fcc34Sopenharmony_ci /* default start_delay value is set to false */ 351c72fcc34Sopenharmony_ci 352c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots); 353c72fcc34Sopenharmony_ci 354c72fcc34Sopenharmony_ci /* LJDFD enable */ 355c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc2 &= ~SSCR2_LJDFD; 356c72fcc34Sopenharmony_ci 357c72fcc34Sopenharmony_ci if (bdiv % 2) { 358c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_calculate(): bdiv %u is not divisible by 2\n", 359c72fcc34Sopenharmony_ci bdiv); 360c72fcc34Sopenharmony_ci return -EINVAL; 361c72fcc34Sopenharmony_ci } 362c72fcc34Sopenharmony_ci 363c72fcc34Sopenharmony_ci /* set asserted frame length to half frame length */ 364c72fcc34Sopenharmony_ci frame_len = bdiv / 2; 365c72fcc34Sopenharmony_ci 366c72fcc34Sopenharmony_ci /* 367c72fcc34Sopenharmony_ci * handle frame polarity, LEFT_J default is rising/active high, 368c72fcc34Sopenharmony_ci * non-inverted(inverted_frame=0) -- active high(SFRMP=1), 369c72fcc34Sopenharmony_ci * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), 370c72fcc34Sopenharmony_ci * so, we should set SFRMP to !inverted_frame. 371c72fcc34Sopenharmony_ci */ 372c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(!inverted_frame ? 1 : 0); 373c72fcc34Sopenharmony_ci 374c72fcc34Sopenharmony_ci /* 375c72fcc34Sopenharmony_ci * for I2S/LEFT_J, the padding has to happen at the end 376c72fcc34Sopenharmony_ci * of each slot 377c72fcc34Sopenharmony_ci */ 378c72fcc34Sopenharmony_ci if (frame_end_padding % 2) { 379c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): frame padding %u not divisible by 2\n", 380c72fcc34Sopenharmony_ci frame_end_padding); 381c72fcc34Sopenharmony_ci return -EINVAL; 382c72fcc34Sopenharmony_ci } 383c72fcc34Sopenharmony_ci 384c72fcc34Sopenharmony_ci slot_end_padding = frame_end_padding / 2; 385c72fcc34Sopenharmony_ci 386c72fcc34Sopenharmony_ci if (slot_end_padding > 15) { 387c72fcc34Sopenharmony_ci /* can't handle padding over 15 bits */ 388c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): slot_end_padding %u > 15 bits\n", 389c72fcc34Sopenharmony_ci slot_end_padding); 390c72fcc34Sopenharmony_ci return -EINVAL; 391c72fcc34Sopenharmony_ci } 392c72fcc34Sopenharmony_ci 393c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding); 394c72fcc34Sopenharmony_ci slot_end_padding >>= SSPSP_DMYSTOP_BITS; 395c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding); 396c72fcc34Sopenharmony_ci 397c72fcc34Sopenharmony_ci break; 398c72fcc34Sopenharmony_ci case SSP_FMT_DSP_A: 399c72fcc34Sopenharmony_ci 400c72fcc34Sopenharmony_ci start_delay = true; 401c72fcc34Sopenharmony_ci 402c72fcc34Sopenharmony_ci /* fallthrough */ 403c72fcc34Sopenharmony_ci 404c72fcc34Sopenharmony_ci case SSP_FMT_DSP_B: 405c72fcc34Sopenharmony_ci 406c72fcc34Sopenharmony_ci /* default start_delay value is set to false */ 407c72fcc34Sopenharmony_ci 408c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_MOD | 409c72fcc34Sopenharmony_ci SSCR0_FRDC(ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots); 410c72fcc34Sopenharmony_ci 411c72fcc34Sopenharmony_ci /* set asserted frame length */ 412c72fcc34Sopenharmony_ci frame_len = 1; /* default */ 413c72fcc34Sopenharmony_ci 414c72fcc34Sopenharmony_ci if (cfs && ssp->ssp_prm[di].frame_pulse_width > 0 && 415c72fcc34Sopenharmony_ci ssp->ssp_prm[di].frame_pulse_width <= 416c72fcc34Sopenharmony_ci SSP_INTEL_FRAME_PULSE_WIDTH_MAX) { 417c72fcc34Sopenharmony_ci frame_len = ssp->ssp_prm[di].frame_pulse_width; 418c72fcc34Sopenharmony_ci } 419c72fcc34Sopenharmony_ci 420c72fcc34Sopenharmony_ci /* frame_pulse_width must less or equal 38 */ 421c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].frame_pulse_width > 422c72fcc34Sopenharmony_ci SSP_INTEL_FRAME_PULSE_WIDTH_MAX) { 423c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): frame_pulse_width > %d\n", 424c72fcc34Sopenharmony_ci SSP_INTEL_FRAME_PULSE_WIDTH_MAX); 425c72fcc34Sopenharmony_ci return -EINVAL; 426c72fcc34Sopenharmony_ci } 427c72fcc34Sopenharmony_ci /* 428c72fcc34Sopenharmony_ci * handle frame polarity, DSP_B default is rising/active high, 429c72fcc34Sopenharmony_ci * non-inverted(inverted_frame=0) -- active high(SFRMP=1), 430c72fcc34Sopenharmony_ci * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), 431c72fcc34Sopenharmony_ci * so, we should set SFRMP to !inverted_frame. 432c72fcc34Sopenharmony_ci */ 433c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMP(!inverted_frame ? 1 : 0); 434c72fcc34Sopenharmony_ci 435c72fcc34Sopenharmony_ci active_tx_slots = popcount(ssp->ssp_prm[di].hw_cfg[hwi].tx_slots); 436c72fcc34Sopenharmony_ci active_rx_slots = popcount(ssp->ssp_prm[di].hw_cfg[hwi].rx_slots); 437c72fcc34Sopenharmony_ci 438c72fcc34Sopenharmony_ci /* 439c72fcc34Sopenharmony_ci * handle TDM mode, TDM mode has padding at the end of 440c72fcc34Sopenharmony_ci * each slot. The amount of padding is equal to result of 441c72fcc34Sopenharmony_ci * subtracting slot width and valid bits per slot. 442c72fcc34Sopenharmony_ci */ 443c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].tdm_per_slot_padding_flag) { 444c72fcc34Sopenharmony_ci frame_end_padding = bdiv - ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots * 445c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width; 446c72fcc34Sopenharmony_ci 447c72fcc34Sopenharmony_ci slot_end_padding = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width - 448c72fcc34Sopenharmony_ci ssp->ssp_prm[di].sample_valid_bits; 449c72fcc34Sopenharmony_ci 450c72fcc34Sopenharmony_ci if (slot_end_padding > 451c72fcc34Sopenharmony_ci SSP_INTEL_SLOT_PADDING_MAX) { 452c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): slot_end_padding > %d\n", 453c72fcc34Sopenharmony_ci SSP_INTEL_SLOT_PADDING_MAX); 454c72fcc34Sopenharmony_ci return -EINVAL; 455c72fcc34Sopenharmony_ci } 456c72fcc34Sopenharmony_ci 457c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_DMYSTOP(slot_end_padding); 458c72fcc34Sopenharmony_ci slot_end_padding >>= SSPSP_DMYSTOP_BITS; 459c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_EDMYSTOP(slot_end_padding); 460c72fcc34Sopenharmony_ci } 461c72fcc34Sopenharmony_ci 462c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK); 463c72fcc34Sopenharmony_ci 464c72fcc34Sopenharmony_ci break; 465c72fcc34Sopenharmony_ci default: 466c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): invalid format 0x%04x\n", 467c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].format); 468c72fcc34Sopenharmony_ci return -EINVAL; 469c72fcc34Sopenharmony_ci } 470c72fcc34Sopenharmony_ci 471c72fcc34Sopenharmony_ci if (start_delay) 472c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_FSRT; 473c72fcc34Sopenharmony_ci 474c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].sspsp |= SSPSP_SFRMWDTH(frame_len); 475c72fcc34Sopenharmony_ci 476c72fcc34Sopenharmony_ci data_size = ssp->ssp_prm[di].sample_valid_bits; 477c72fcc34Sopenharmony_ci 478c72fcc34Sopenharmony_ci if (data_size > 16) 479c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); 480c72fcc34Sopenharmony_ci else 481c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_DSIZE(data_size); 482c72fcc34Sopenharmony_ci 483c72fcc34Sopenharmony_ci end_padding = 0; 484c72fcc34Sopenharmony_ci total_sample_size = ssp->ssp_prm[di].hw_cfg[hwi].tdm_slot_width * 485c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].tdm_slots; 486c72fcc34Sopenharmony_ci while (ssp->ssp_prm[di].io_clk % ((total_sample_size + end_padding) * 487c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate)) { 488c72fcc34Sopenharmony_ci if (++end_padding >= 256) 489c72fcc34Sopenharmony_ci break; 490c72fcc34Sopenharmony_ci } 491c72fcc34Sopenharmony_ci 492c72fcc34Sopenharmony_ci if (end_padding >= 256) 493c72fcc34Sopenharmony_ci return -EINVAL; 494c72fcc34Sopenharmony_ci 495c72fcc34Sopenharmony_ci /* calc scr divisor */ 496c72fcc34Sopenharmony_ci clk_div = ssp->ssp_prm[di].io_clk / ((total_sample_size + end_padding) * 497c72fcc34Sopenharmony_ci ssp->ssp_prm[di].hw_cfg[hwi].fsync_rate); 498c72fcc34Sopenharmony_ci if (clk_div >= 4095) 499c72fcc34Sopenharmony_ci return -EINVAL; 500c72fcc34Sopenharmony_ci 501c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_SCR(clk_div - 1); 502c72fcc34Sopenharmony_ci 503c72fcc34Sopenharmony_ci /* setting TFT and RFT */ 504c72fcc34Sopenharmony_ci switch (ssp->ssp_prm[di].sample_valid_bits) { 505c72fcc34Sopenharmony_ci case 16: 506c72fcc34Sopenharmony_ci /* use 2 bytes for each slot */ 507c72fcc34Sopenharmony_ci sample_width = 2; 508c72fcc34Sopenharmony_ci break; 509c72fcc34Sopenharmony_ci case 24: 510c72fcc34Sopenharmony_ci case 32: 511c72fcc34Sopenharmony_ci /* use 4 bytes for each slot */ 512c72fcc34Sopenharmony_ci sample_width = 4; 513c72fcc34Sopenharmony_ci break; 514c72fcc34Sopenharmony_ci default: 515c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): sample_valid_bits %u\n", 516c72fcc34Sopenharmony_ci ssp->ssp_prm[di].sample_valid_bits); 517c72fcc34Sopenharmony_ci return -EINVAL; 518c72fcc34Sopenharmony_ci } 519c72fcc34Sopenharmony_ci 520c72fcc34Sopenharmony_ci tft = MIN((uint32_t)(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK), 521c72fcc34Sopenharmony_ci sample_width * active_tx_slots); 522c72fcc34Sopenharmony_ci rft = MIN((uint32_t)(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK), 523c72fcc34Sopenharmony_ci sample_width * active_rx_slots); 524c72fcc34Sopenharmony_ci 525c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc3 |= SSCR3_TX(tft) | SSCR3_RX(rft); 526c72fcc34Sopenharmony_ci 527c72fcc34Sopenharmony_ci /* calc mn divisor */ 528c72fcc34Sopenharmony_ci if (ssp->ssp_prm[di].io_clk % ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate) { 529c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_config(): io_clk not divisible with mclk\n"); 530c72fcc34Sopenharmony_ci return -EINVAL; 531c72fcc34Sopenharmony_ci } 532c72fcc34Sopenharmony_ci 533c72fcc34Sopenharmony_ci clk_div = ssp->ssp_prm[di].io_clk / ssp->ssp_prm[di].hw_cfg[hwi].mclk_rate; 534c72fcc34Sopenharmony_ci if (clk_div > 1) 535c72fcc34Sopenharmony_ci clk_div -= 2; 536c72fcc34Sopenharmony_ci else 537c72fcc34Sopenharmony_ci clk_div = 0xFFF; /* bypass clk divider */ 538c72fcc34Sopenharmony_ci 539c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].mdivr = clk_div; 540c72fcc34Sopenharmony_ci /* clock will always go through the divider */ 541c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].ssc0 |= SSCR0_ECS; 542c72fcc34Sopenharmony_ci /* enable divider for this clock id */ 543c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].mdivc |= BIT(ssp->ssp_prm[di].mclk_id); 544c72fcc34Sopenharmony_ci /* set mclk source always for audio cardinal clock */ 545c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].mdivc |= MCDSS(SSP_CLOCK_AUDIO_CARDINAL); 546c72fcc34Sopenharmony_ci /* set bclk source for audio cardinal clock */ 547c72fcc34Sopenharmony_ci ssp->ssp_blob[di][hwi].mdivc |= MNDSS(SSP_CLOCK_AUDIO_CARDINAL); 548c72fcc34Sopenharmony_ci 549c72fcc34Sopenharmony_ci return 0; 550c72fcc34Sopenharmony_ci} 551c72fcc34Sopenharmony_ci 552c72fcc34Sopenharmony_cistatic int ssp_calculate_intern_ext(struct intel_nhlt_params *nhlt, int hwi) 553c72fcc34Sopenharmony_ci{ 554c72fcc34Sopenharmony_ci size_t aux_size, mn_size, clk_size, tr_size, run_size, sync_size, node_size, ext_size, 555c72fcc34Sopenharmony_ci link_size, size, total_size; 556c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp; 557c72fcc34Sopenharmony_ci struct ssp_config_aux *aux; 558c72fcc34Sopenharmony_ci struct ssp_intel_aux_tlv *tlv; 559c72fcc34Sopenharmony_ci struct ssp_intel_mn_ctl *mn; 560c72fcc34Sopenharmony_ci struct ssp_intel_clk_ctl *clk; 561c72fcc34Sopenharmony_ci struct ssp_intel_tr_ctl *tr; 562c72fcc34Sopenharmony_ci struct ssp_intel_run_ctl *run; 563c72fcc34Sopenharmony_ci struct ssp_intel_sync_ctl *sync; 564c72fcc34Sopenharmony_ci struct ssp_intel_node_ctl *node; 565c72fcc34Sopenharmony_ci struct ssp_intel_ext_ctl *ext; 566c72fcc34Sopenharmony_ci struct ssp_intel_link_ctl *link; 567c72fcc34Sopenharmony_ci uint8_t *aux_blob; 568c72fcc34Sopenharmony_ci uint32_t enabled; 569c72fcc34Sopenharmony_ci unsigned int i; 570c72fcc34Sopenharmony_ci int di; 571c72fcc34Sopenharmony_ci 572c72fcc34Sopenharmony_ci aux_size = sizeof(struct ssp_intel_aux_tlv); 573c72fcc34Sopenharmony_ci mn_size = sizeof(struct ssp_intel_mn_ctl); 574c72fcc34Sopenharmony_ci clk_size = sizeof(struct ssp_intel_clk_ctl); 575c72fcc34Sopenharmony_ci tr_size = sizeof(struct ssp_intel_tr_ctl); 576c72fcc34Sopenharmony_ci run_size = sizeof(struct ssp_intel_run_ctl); 577c72fcc34Sopenharmony_ci sync_size = sizeof(struct ssp_intel_sync_ctl); 578c72fcc34Sopenharmony_ci node_size = sizeof(struct ssp_intel_node_ctl); 579c72fcc34Sopenharmony_ci ext_size = sizeof(struct ssp_intel_ext_ctl); 580c72fcc34Sopenharmony_ci link_size = sizeof(struct ssp_intel_link_ctl); 581c72fcc34Sopenharmony_ci 582c72fcc34Sopenharmony_ci ssp = (struct intel_ssp_params *)nhlt->ssp_params; 583c72fcc34Sopenharmony_ci di = ssp->ssp_count; 584c72fcc34Sopenharmony_ci enabled = ssp->ssp_prm[di].aux_cfg[hwi].enabled; 585c72fcc34Sopenharmony_ci aux = &(ssp->ssp_prm[di].aux_cfg[hwi]); 586c72fcc34Sopenharmony_ci aux_blob = ssp->ssp_blob_ext[di][hwi].aux_blob; 587c72fcc34Sopenharmony_ci total_size = 0; 588c72fcc34Sopenharmony_ci size = 0; 589c72fcc34Sopenharmony_ci 590c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_MN_DIVIDER_CONTROLS)) { 591c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 592c72fcc34Sopenharmony_ci mn = (struct ssp_intel_mn_ctl *)(aux_blob + aux_size); 593c72fcc34Sopenharmony_ci size = mn_size + aux_size; 594c72fcc34Sopenharmony_ci tlv->type = SSP_MN_DIVIDER_CONTROLS; 595c72fcc34Sopenharmony_ci tlv->size = mn_size; 596c72fcc34Sopenharmony_ci mn->div_m = aux->mn.m_div; 597c72fcc34Sopenharmony_ci mn->div_n = aux->mn.n_div; 598c72fcc34Sopenharmony_ci aux_blob += size; 599c72fcc34Sopenharmony_ci total_size += size; 600c72fcc34Sopenharmony_ci } 601c72fcc34Sopenharmony_ci 602c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_CLK_CONTROLS)) { 603c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 604c72fcc34Sopenharmony_ci clk = (struct ssp_intel_clk_ctl *)(aux_blob + aux_size); 605c72fcc34Sopenharmony_ci size = clk_size + aux_size; 606c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_CLK_CONTROLS; 607c72fcc34Sopenharmony_ci tlv->size = clk_size; 608c72fcc34Sopenharmony_ci clk->start |= SET_BITS(15, 0, aux->clk.clock_warm_up); 609c72fcc34Sopenharmony_ci clk->start |= SET_BIT(16, aux->clk.mclk); 610c72fcc34Sopenharmony_ci clk->start |= SET_BIT(17, aux->clk.warm_up_ovr); 611c72fcc34Sopenharmony_ci clk->stop |= SET_BITS(15, 0, aux->clk.clock_stop_delay); 612c72fcc34Sopenharmony_ci clk->stop |= SET_BIT(16, aux->clk.keep_running); 613c72fcc34Sopenharmony_ci clk->stop |= SET_BIT(17, aux->clk.clock_stop_ovr); 614c72fcc34Sopenharmony_ci aux_blob += size; 615c72fcc34Sopenharmony_ci total_size += size; 616c72fcc34Sopenharmony_ci } 617c72fcc34Sopenharmony_ci 618c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_TRANSMISSION_START)) { 619c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 620c72fcc34Sopenharmony_ci tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size); 621c72fcc34Sopenharmony_ci size = tr_size + aux_size; 622c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_TRANSMISSION_START; 623c72fcc34Sopenharmony_ci tlv->size = tr_size; 624c72fcc34Sopenharmony_ci tr->sampling_frequency = aux->tr_start.sampling_frequency; 625c72fcc34Sopenharmony_ci tr->bit_depth = aux->tr_start.bit_depth; 626c72fcc34Sopenharmony_ci tr->channel_map = aux->tr_start.channel_map; 627c72fcc34Sopenharmony_ci tr->channel_config = aux->tr_start.channel_config; 628c72fcc34Sopenharmony_ci tr->interleaving_style = aux->tr_start.interleaving_style; 629c72fcc34Sopenharmony_ci tr->format |= SET_BITS(7, 0, aux->tr_start.number_of_channels); 630c72fcc34Sopenharmony_ci tr->format |= SET_BITS(15, 8, aux->tr_start.valid_bit_depth); 631c72fcc34Sopenharmony_ci tr->format |= SET_BITS(23, 16, aux->tr_start.sample_type); 632c72fcc34Sopenharmony_ci aux_blob += size; 633c72fcc34Sopenharmony_ci total_size += size; 634c72fcc34Sopenharmony_ci } 635c72fcc34Sopenharmony_ci 636c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_TRANSMISSION_STOP)) { 637c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 638c72fcc34Sopenharmony_ci tr = (struct ssp_intel_tr_ctl *)(aux_blob + aux_size); 639c72fcc34Sopenharmony_ci size = tr_size + aux_size; 640c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_TRANSMISSION_STOP; 641c72fcc34Sopenharmony_ci tlv->size = tr_size; 642c72fcc34Sopenharmony_ci tr->sampling_frequency = aux->tr_stop.sampling_frequency; 643c72fcc34Sopenharmony_ci tr->bit_depth = aux->tr_stop.bit_depth; 644c72fcc34Sopenharmony_ci tr->channel_map = aux->tr_stop.channel_map; 645c72fcc34Sopenharmony_ci tr->channel_config = aux->tr_stop.channel_config; 646c72fcc34Sopenharmony_ci tr->interleaving_style = aux->tr_stop.interleaving_style; 647c72fcc34Sopenharmony_ci tr->format |= SET_BITS(7, 0, aux->tr_stop.number_of_channels); 648c72fcc34Sopenharmony_ci tr->format |= SET_BITS(15, 8, aux->tr_stop.valid_bit_depth); 649c72fcc34Sopenharmony_ci tr->format |= SET_BITS(23, 16, aux->tr_stop.sample_type); 650c72fcc34Sopenharmony_ci aux_blob += size; 651c72fcc34Sopenharmony_ci total_size += size; 652c72fcc34Sopenharmony_ci } 653c72fcc34Sopenharmony_ci 654c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_ALWAYS_RUNNING_MODE)) { 655c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 656c72fcc34Sopenharmony_ci run = (struct ssp_intel_run_ctl *)(aux_blob + aux_size); 657c72fcc34Sopenharmony_ci size = run_size + aux_size; 658c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_ALWAYS_RUNNING_MODE; 659c72fcc34Sopenharmony_ci tlv->size = run_size; 660c72fcc34Sopenharmony_ci run->enabled = aux->run.always_run; 661c72fcc34Sopenharmony_ci aux_blob += size; 662c72fcc34Sopenharmony_ci total_size += size; 663c72fcc34Sopenharmony_ci } 664c72fcc34Sopenharmony_ci 665c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_SYNC_DATA)) { 666c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 667c72fcc34Sopenharmony_ci sync = (struct ssp_intel_sync_ctl *)(aux_blob + aux_size); 668c72fcc34Sopenharmony_ci size = sync_size + aux_size; 669c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_SYNC_DATA; 670c72fcc34Sopenharmony_ci tlv->size = sync_size; 671c72fcc34Sopenharmony_ci sync->sync_denominator = aux->sync.sync_denominator; 672c72fcc34Sopenharmony_ci sync->count = aux->sync.count; 673c72fcc34Sopenharmony_ci aux_blob += size; 674c72fcc34Sopenharmony_ci total_size += size; 675c72fcc34Sopenharmony_ci for (i = 0; i < sync->count; i++) { 676c72fcc34Sopenharmony_ci node = (struct ssp_intel_node_ctl *)(aux_blob); 677c72fcc34Sopenharmony_ci size = node_size; 678c72fcc34Sopenharmony_ci node->node_id = aux->sync.nodes[i].node_id; 679c72fcc34Sopenharmony_ci node->sampling_rate = aux->sync.nodes[i].sampling_rate; 680c72fcc34Sopenharmony_ci tlv->size += node_size; 681c72fcc34Sopenharmony_ci aux_blob += size; 682c72fcc34Sopenharmony_ci total_size += size; 683c72fcc34Sopenharmony_ci } 684c72fcc34Sopenharmony_ci } 685c72fcc34Sopenharmony_ci 686c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_DMA_CLK_CONTROLS_EXT)) { 687c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 688c72fcc34Sopenharmony_ci ext = (struct ssp_intel_ext_ctl *)(aux_blob + aux_size); 689c72fcc34Sopenharmony_ci size = ext_size + aux_size; 690c72fcc34Sopenharmony_ci tlv->type = SSP_DMA_CLK_CONTROLS_EXT; 691c72fcc34Sopenharmony_ci tlv->size = ext_size; 692c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(0, aux->ext.mclk_policy_override); 693c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(1, aux->ext.mclk_always_running); 694c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(2, aux->ext.mclk_starts_on_gtw_init); 695c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(3, aux->ext.mclk_starts_on_run); 696c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(4, aux->ext.mclk_starts_on_pause); 697c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(5, aux->ext.mclk_stops_on_pause); 698c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(6, aux->ext.mclk_stops_on_reset); 699c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(8, aux->ext.bclk_policy_override); 700c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(9, aux->ext.bclk_always_running); 701c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(10, aux->ext.bclk_starts_on_gtw_init); 702c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(11, aux->ext.bclk_starts_on_run); 703c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(12, aux->ext.bclk_starts_on_pause); 704c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(13, aux->ext.bclk_stops_on_pause); 705c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(14, aux->ext.bclk_stops_on_reset); 706c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(16, aux->ext.sync_policy_override); 707c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(17, aux->ext.sync_always_running); 708c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(18, aux->ext.sync_starts_on_gtw_init); 709c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(19, aux->ext.sync_starts_on_run); 710c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(20, aux->ext.sync_starts_on_pause); 711c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(21, aux->ext.sync_stops_on_pause); 712c72fcc34Sopenharmony_ci ext->ext_data |= SET_BIT(22, aux->ext.sync_stops_on_reset); 713c72fcc34Sopenharmony_ci aux_blob += size; 714c72fcc34Sopenharmony_ci total_size += size; 715c72fcc34Sopenharmony_ci } 716c72fcc34Sopenharmony_ci 717c72fcc34Sopenharmony_ci if (enabled & BIT(SSP_LINK_CLK_SOURCE)) { 718c72fcc34Sopenharmony_ci tlv = (struct ssp_intel_aux_tlv *)aux_blob; 719c72fcc34Sopenharmony_ci link = (struct ssp_intel_link_ctl *)(aux_blob + aux_size); 720c72fcc34Sopenharmony_ci size = link_size + aux_size; 721c72fcc34Sopenharmony_ci tlv->type = SSP_LINK_CLK_SOURCE; 722c72fcc34Sopenharmony_ci tlv->size = link_size; 723c72fcc34Sopenharmony_ci link->clock_source = aux->link.clock_source; 724c72fcc34Sopenharmony_ci aux_blob += size; 725c72fcc34Sopenharmony_ci total_size += size; 726c72fcc34Sopenharmony_ci } 727c72fcc34Sopenharmony_ci 728c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[di][hwi].size = total_size; 729c72fcc34Sopenharmony_ci 730c72fcc34Sopenharmony_ci return 0; 731c72fcc34Sopenharmony_ci} 732c72fcc34Sopenharmony_ci 733c72fcc34Sopenharmony_ci 734c72fcc34Sopenharmony_ci 735c72fcc34Sopenharmony_ciint ssp_calculate(struct intel_nhlt_params *nhlt) 736c72fcc34Sopenharmony_ci{ 737c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 738c72fcc34Sopenharmony_ci unsigned int i; 739c72fcc34Sopenharmony_ci 740c72fcc34Sopenharmony_ci if (!ssp) 741c72fcc34Sopenharmony_ci return -EINVAL; 742c72fcc34Sopenharmony_ci 743c72fcc34Sopenharmony_ci /* calculate blob for every hw config */ 744c72fcc34Sopenharmony_ci for (i = 0; i < ssp->ssp_hw_config_count[ssp->ssp_count]; i++) { 745c72fcc34Sopenharmony_ci if (ssp_calculate_intern(nhlt, i) < 0) 746c72fcc34Sopenharmony_ci return -EINVAL; 747c72fcc34Sopenharmony_ci if (ssp_calculate_intern_ext(nhlt, i) < 0) 748c72fcc34Sopenharmony_ci return -EINVAL; 749c72fcc34Sopenharmony_ci /* v15 blob is made from legacy blob, so it can't fail */ 750c72fcc34Sopenharmony_ci ssp_calculate_intern_v15(nhlt, i); 751c72fcc34Sopenharmony_ci } 752c72fcc34Sopenharmony_ci 753c72fcc34Sopenharmony_ci ssp_print_internal(ssp); 754c72fcc34Sopenharmony_ci ssp_print_calculated(ssp); 755c72fcc34Sopenharmony_ci 756c72fcc34Sopenharmony_ci ssp->ssp_count++; 757c72fcc34Sopenharmony_ci 758c72fcc34Sopenharmony_ci return 0; 759c72fcc34Sopenharmony_ci} 760c72fcc34Sopenharmony_ci 761c72fcc34Sopenharmony_ciint ssp_get_dir(struct intel_nhlt_params *nhlt, int dai_index, uint8_t *dir) 762c72fcc34Sopenharmony_ci{ 763c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 764c72fcc34Sopenharmony_ci 765c72fcc34Sopenharmony_ci if (!ssp) 766c72fcc34Sopenharmony_ci return -EINVAL; 767c72fcc34Sopenharmony_ci 768c72fcc34Sopenharmony_ci *dir = ssp->ssp_prm[dai_index].direction; 769c72fcc34Sopenharmony_ci 770c72fcc34Sopenharmony_ci return 0; 771c72fcc34Sopenharmony_ci} 772c72fcc34Sopenharmony_ci 773c72fcc34Sopenharmony_ciint ssp_get_params(struct intel_nhlt_params *nhlt, int dai_index, uint32_t *virtualbus_id, 774c72fcc34Sopenharmony_ci uint32_t *formats_count, uint32_t *device_type, uint32_t *direction) 775c72fcc34Sopenharmony_ci{ 776c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 777c72fcc34Sopenharmony_ci 778c72fcc34Sopenharmony_ci if (!ssp) 779c72fcc34Sopenharmony_ci return -EINVAL; 780c72fcc34Sopenharmony_ci 781c72fcc34Sopenharmony_ci *virtualbus_id = ssp->ssp_dai_index[dai_index]; 782c72fcc34Sopenharmony_ci *formats_count = ssp->ssp_hw_config_count[dai_index]; 783c72fcc34Sopenharmony_ci if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_BT_SIDEBAND) 784c72fcc34Sopenharmony_ci *device_type = NHLT_DEVICE_TYPE_SSP_BT_SIDEBAND; 785c72fcc34Sopenharmony_ci else 786c72fcc34Sopenharmony_ci *device_type = 0; 787c72fcc34Sopenharmony_ci if (ssp->ssp_prm[dai_index].quirks & SSP_INTEL_QUIRK_RENDER_FEEDBACK) { 788c72fcc34Sopenharmony_ci if (*direction == NHLT_ENDPOINT_DIRECTION_RENDER) 789c72fcc34Sopenharmony_ci *direction = NHLT_ENDPOINT_DIRECTION_RENDER_WITH_LOOPBACK; 790c72fcc34Sopenharmony_ci else if (*direction == NHLT_ENDPOINT_DIRECTION_CAPTURE) 791c72fcc34Sopenharmony_ci *direction = NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER; 792c72fcc34Sopenharmony_ci } 793c72fcc34Sopenharmony_ci 794c72fcc34Sopenharmony_ci return 0; 795c72fcc34Sopenharmony_ci} 796c72fcc34Sopenharmony_ci 797c72fcc34Sopenharmony_ciint ssp_get_hw_params(struct intel_nhlt_params *nhlt, int dai_index, int hw_index, 798c72fcc34Sopenharmony_ci uint32_t *sample_rate, uint16_t *channel_count, uint32_t *bits_per_sample) 799c72fcc34Sopenharmony_ci{ 800c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 801c72fcc34Sopenharmony_ci 802c72fcc34Sopenharmony_ci if (!ssp) 803c72fcc34Sopenharmony_ci return -EINVAL; 804c72fcc34Sopenharmony_ci 805c72fcc34Sopenharmony_ci *channel_count = ssp->ssp_prm[dai_index].hw_cfg[hw_index].tdm_slots; 806c72fcc34Sopenharmony_ci *sample_rate = ssp->ssp_prm[dai_index].hw_cfg[hw_index].fsync_rate; 807c72fcc34Sopenharmony_ci *bits_per_sample = ssp->ssp_prm[dai_index].hw_cfg[hw_index].tdm_slot_width; 808c72fcc34Sopenharmony_ci 809c72fcc34Sopenharmony_ci return 0; 810c72fcc34Sopenharmony_ci} 811c72fcc34Sopenharmony_ci 812c72fcc34Sopenharmony_ci/* 813c72fcc34Sopenharmony_ci * Build ssp vendor blob from calculated parameters. 814c72fcc34Sopenharmony_ci * 815c72fcc34Sopenharmony_ci * Supposed to be called after all ssp DAIs are parsed from topology and the final nhlt blob is 816c72fcc34Sopenharmony_ci * generated. 817c72fcc34Sopenharmony_ci */ 818c72fcc34Sopenharmony_ciint ssp_get_vendor_blob_size(struct intel_nhlt_params *nhlt, int dai_index, 819c72fcc34Sopenharmony_ci int hw_config_index, size_t *size) 820c72fcc34Sopenharmony_ci{ 821c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 822c72fcc34Sopenharmony_ci 823c72fcc34Sopenharmony_ci if (!ssp) 824c72fcc34Sopenharmony_ci return -EINVAL; 825c72fcc34Sopenharmony_ci 826c72fcc34Sopenharmony_ci /* set size for the blob */ 827c72fcc34Sopenharmony_ci if (ssp->ssp_prm[dai_index].version == SSP_BLOB_VER_1_5) 828c72fcc34Sopenharmony_ci *size = ssp->ssp_blob_1_5[dai_index][hw_config_index].size; 829c72fcc34Sopenharmony_ci else 830c72fcc34Sopenharmony_ci /* legacy */ 831c72fcc34Sopenharmony_ci *size = sizeof(struct ssp_intel_config_data) + 832c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[dai_index][hw_config_index].size; 833c72fcc34Sopenharmony_ci 834c72fcc34Sopenharmony_ci return 0; 835c72fcc34Sopenharmony_ci} 836c72fcc34Sopenharmony_ci 837c72fcc34Sopenharmony_ciint ssp_get_vendor_blob_count(struct intel_nhlt_params *nhlt) 838c72fcc34Sopenharmony_ci{ 839c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 840c72fcc34Sopenharmony_ci 841c72fcc34Sopenharmony_ci if (!ssp || !ssp->ssp_count) 842c72fcc34Sopenharmony_ci return -EINVAL; 843c72fcc34Sopenharmony_ci 844c72fcc34Sopenharmony_ci return ssp->ssp_count; 845c72fcc34Sopenharmony_ci} 846c72fcc34Sopenharmony_ci 847c72fcc34Sopenharmony_ci/* Get the size of dynamic vendor blob to reserve proper amount of memory */ 848c72fcc34Sopenharmony_ciint ssp_get_vendor_blob(struct intel_nhlt_params *nhlt, uint8_t *vendor_blob, 849c72fcc34Sopenharmony_ci int dai_index, int hw_config_index) 850c72fcc34Sopenharmony_ci{ 851c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 852c72fcc34Sopenharmony_ci uint32_t basic_len, clock_len; 853c72fcc34Sopenharmony_ci 854c72fcc34Sopenharmony_ci if (!ssp) 855c72fcc34Sopenharmony_ci return -EINVAL; 856c72fcc34Sopenharmony_ci 857c72fcc34Sopenharmony_ci /* top level struct */ 858c72fcc34Sopenharmony_ci if (ssp->ssp_prm[dai_index].version == SSP_BLOB_VER_1_5) { 859c72fcc34Sopenharmony_ci basic_len = sizeof(struct ssp_intel_config_data_1_5); 860c72fcc34Sopenharmony_ci clock_len = sizeof(uint32_t) * ssp->ssp_prm[dai_index].mdivr[hw_config_index].count; 861c72fcc34Sopenharmony_ci /* basic data */ 862c72fcc34Sopenharmony_ci memcpy(vendor_blob, &ssp->ssp_blob_1_5[dai_index][hw_config_index], basic_len); 863c72fcc34Sopenharmony_ci /* clock data */ 864c72fcc34Sopenharmony_ci memcpy(vendor_blob + basic_len, 865c72fcc34Sopenharmony_ci &ssp->ssp_prm[dai_index].mdivr[hw_config_index].mdivrs[0], clock_len); 866c72fcc34Sopenharmony_ci /* ext data */ 867c72fcc34Sopenharmony_ci memcpy(vendor_blob + basic_len + clock_len, 868c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[dai_index][hw_config_index].aux_blob, 869c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[dai_index][hw_config_index].size); 870c72fcc34Sopenharmony_ci } 871c72fcc34Sopenharmony_ci else { 872c72fcc34Sopenharmony_ci basic_len = sizeof(struct ssp_intel_config_data); 873c72fcc34Sopenharmony_ci /*basic data */ 874c72fcc34Sopenharmony_ci memcpy(vendor_blob, &ssp->ssp_blob[dai_index][hw_config_index], basic_len); 875c72fcc34Sopenharmony_ci /* ext data */ 876c72fcc34Sopenharmony_ci memcpy(vendor_blob + basic_len, 877c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[dai_index][hw_config_index].aux_blob, 878c72fcc34Sopenharmony_ci ssp->ssp_blob_ext[dai_index][hw_config_index].size); 879c72fcc34Sopenharmony_ci } 880c72fcc34Sopenharmony_ci 881c72fcc34Sopenharmony_ci return 0; 882c72fcc34Sopenharmony_ci} 883c72fcc34Sopenharmony_ci 884c72fcc34Sopenharmony_ciint ssp_set_params(struct intel_nhlt_params *nhlt, const char *dir, int dai_index, int io_clk, 885c72fcc34Sopenharmony_ci int bclk_delay, int sample_bits, int mclk_id, int clks_control, 886c72fcc34Sopenharmony_ci int frame_pulse_width, const char *tdm_padding_per_slot, const char *quirks, 887c72fcc34Sopenharmony_ci int version) 888c72fcc34Sopenharmony_ci{ 889c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 890c72fcc34Sopenharmony_ci char delim[] = ","; 891c72fcc34Sopenharmony_ci char *buf, *token = NULL; 892c72fcc34Sopenharmony_ci 893c72fcc34Sopenharmony_ci if (!ssp) 894c72fcc34Sopenharmony_ci return -EINVAL; 895c72fcc34Sopenharmony_ci 896c72fcc34Sopenharmony_ci if (dir) { 897c72fcc34Sopenharmony_ci if (!strcmp(dir, "playback")) 898c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].direction = NHLT_ENDPOINT_DIRECTION_RENDER; 899c72fcc34Sopenharmony_ci else if (!strcmp(dir, "capture")) 900c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].direction = NHLT_ENDPOINT_DIRECTION_CAPTURE; 901c72fcc34Sopenharmony_ci else if (!strcmp(dir, "duplex")) 902c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].direction = 903c72fcc34Sopenharmony_ci NHLT_ENDPOINT_DIRECTION_FEEDBACK_FOR_RENDER + 1; 904c72fcc34Sopenharmony_ci else 905c72fcc34Sopenharmony_ci return -EINVAL; 906c72fcc34Sopenharmony_ci } 907c72fcc34Sopenharmony_ci ssp->ssp_dai_index[ssp->ssp_count] = dai_index; 908c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].io_clk = io_clk; 909c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].bclk_delay = bclk_delay; 910c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].sample_valid_bits = sample_bits; 911c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].mclk_id = mclk_id; 912c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].clks_control = clks_control; 913c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].frame_pulse_width = frame_pulse_width; 914c72fcc34Sopenharmony_ci /* let's compare the lower 16 bits as we don't send the signature from topology */ 915c72fcc34Sopenharmony_ci if (version == (SSP_BLOB_VER_1_5 & ((1 << 16) - 1))) 916c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].version = SSP_BLOB_VER_1_5; 917c72fcc34Sopenharmony_ci if (tdm_padding_per_slot && !strcmp(tdm_padding_per_slot, "true")) 918c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 1; 919c72fcc34Sopenharmony_ci else 920c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].tdm_per_slot_padding_flag = 0; 921c72fcc34Sopenharmony_ci 922c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].quirks = 0; 923c72fcc34Sopenharmony_ci 924c72fcc34Sopenharmony_ci if (quirks) { 925c72fcc34Sopenharmony_ci buf = strdup(quirks); 926c72fcc34Sopenharmony_ci if (!buf) 927c72fcc34Sopenharmony_ci return -ENOMEM; 928c72fcc34Sopenharmony_ci 929c72fcc34Sopenharmony_ci token = strtok(buf, delim); 930c72fcc34Sopenharmony_ci 931c72fcc34Sopenharmony_ci while (token) { 932c72fcc34Sopenharmony_ci if (!strcmp(token, "lbm_mode")) 933c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_LBM; 934c72fcc34Sopenharmony_ci else if (!strcmp(token, "bt_sideband")) 935c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_BT_SIDEBAND; 936c72fcc34Sopenharmony_ci else if (!strcmp(token, "render_feedback")) { 937c72fcc34Sopenharmony_ci if (!strcmp(dir, "duplex")) 938c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].quirks |= SSP_INTEL_QUIRK_RENDER_FEEDBACK; 939c72fcc34Sopenharmony_ci } else { 940c72fcc34Sopenharmony_ci fprintf(stderr, "ssp_set_params(): unknown quirk %s\n", token); 941c72fcc34Sopenharmony_ci free(buf); 942c72fcc34Sopenharmony_ci return -EINVAL; 943c72fcc34Sopenharmony_ci } 944c72fcc34Sopenharmony_ci 945c72fcc34Sopenharmony_ci token = strtok(NULL, delim); 946c72fcc34Sopenharmony_ci } 947c72fcc34Sopenharmony_ci 948c72fcc34Sopenharmony_ci free(buf); 949c72fcc34Sopenharmony_ci } 950c72fcc34Sopenharmony_ci 951c72fcc34Sopenharmony_ci /* reset hw config count for this ssp instance */ 952c72fcc34Sopenharmony_ci ssp->ssp_hw_config_count[ssp->ssp_count] = 0; 953c72fcc34Sopenharmony_ci 954c72fcc34Sopenharmony_ci return 0; 955c72fcc34Sopenharmony_ci} 956c72fcc34Sopenharmony_ci 957c72fcc34Sopenharmony_ciint ssp_hw_set_params(struct intel_nhlt_params *nhlt, const char *format, 958c72fcc34Sopenharmony_ci const char *mclk ATTRIBUTE_UNUSED, 959c72fcc34Sopenharmony_ci const char *bclk, const char *bclk_invert, const char *fsync, 960c72fcc34Sopenharmony_ci const char *fsync_invert, int mclk_freq, int bclk_freq, int fsync_freq, 961c72fcc34Sopenharmony_ci int tdm_slots, int tdm_slot_width, int tx_slots, int rx_slots) 962c72fcc34Sopenharmony_ci{ 963c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 964c72fcc34Sopenharmony_ci uint32_t hwi; 965c72fcc34Sopenharmony_ci 966c72fcc34Sopenharmony_ci if (!ssp) 967c72fcc34Sopenharmony_ci return -EINVAL; 968c72fcc34Sopenharmony_ci 969c72fcc34Sopenharmony_ci /* check that the strings are defined ?*/ 970c72fcc34Sopenharmony_ci 971c72fcc34Sopenharmony_ci /* compose format out of clock related string variables */ 972c72fcc34Sopenharmony_ci hwi = ssp->ssp_hw_config_count[ssp->ssp_count]; 973c72fcc34Sopenharmony_ci 974c72fcc34Sopenharmony_ci if (!strcmp(format, "I2S")) { 975c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_I2S; 976c72fcc34Sopenharmony_ci } else if (!strcmp(format, "RIGHT_J")) { 977c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_RIGHT_J; 978c72fcc34Sopenharmony_ci } else if (!strcmp(format, "LEFT_J")) { 979c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_LEFT_J; 980c72fcc34Sopenharmony_ci } else if (!strcmp(format, "DSP_A")) { 981c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_DSP_A; 982c72fcc34Sopenharmony_ci } else if (!strcmp(format, "DSP_B")) { 983c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format = SSP_FMT_DSP_B; 984c72fcc34Sopenharmony_ci } else { 985c72fcc34Sopenharmony_ci fprintf(stderr, "no valid format specified for ssp: %s\n", format); 986c72fcc34Sopenharmony_ci return -EINVAL; 987c72fcc34Sopenharmony_ci } 988c72fcc34Sopenharmony_ci 989c72fcc34Sopenharmony_ci /* clock directions wrt codec */ 990c72fcc34Sopenharmony_ci if (bclk && !strcmp(bclk, "codec_provider")) { 991c72fcc34Sopenharmony_ci /* codec is bclk provider */ 992c72fcc34Sopenharmony_ci if (fsync && !strcmp(fsync, "codec_provider")) 993c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBP_CFP; 994c72fcc34Sopenharmony_ci else 995c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBP_CFC; 996c72fcc34Sopenharmony_ci } else { 997c72fcc34Sopenharmony_ci /* codec is bclk consumer */ 998c72fcc34Sopenharmony_ci if (fsync && !strcmp(fsync, "codec_provider")) 999c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBC_CFP; 1000c72fcc34Sopenharmony_ci else 1001c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_CBC_CFC; 1002c72fcc34Sopenharmony_ci } 1003c72fcc34Sopenharmony_ci 1004c72fcc34Sopenharmony_ci /* inverted clocks ? */ 1005c72fcc34Sopenharmony_ci if (bclk_invert && !strcmp(bclk_invert, "true")) { 1006c72fcc34Sopenharmony_ci if (fsync_invert && !strcmp(fsync_invert, "true")) 1007c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_IB_IF; 1008c72fcc34Sopenharmony_ci else 1009c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_IB_NF; 1010c72fcc34Sopenharmony_ci } else { 1011c72fcc34Sopenharmony_ci if (fsync_invert && !strcmp(fsync_invert, "true")) 1012c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_NB_IF; 1013c72fcc34Sopenharmony_ci else 1014c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].format |= SSP_FMT_NB_NF; 1015c72fcc34Sopenharmony_ci } 1016c72fcc34Sopenharmony_ci 1017c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].mclk_rate = mclk_freq; 1018c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].bclk_rate = bclk_freq; 1019c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].fsync_rate = fsync_freq; 1020c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tdm_slots = tdm_slots; 1021c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tdm_slot_width = tdm_slot_width; 1022c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].tx_slots = tx_slots; 1023c72fcc34Sopenharmony_ci ssp->ssp_prm[ssp->ssp_count].hw_cfg[hwi].rx_slots = rx_slots; 1024c72fcc34Sopenharmony_ci 1025c72fcc34Sopenharmony_ci ssp->ssp_hw_config_count[ssp->ssp_count]++; 1026c72fcc34Sopenharmony_ci 1027c72fcc34Sopenharmony_ci return 0; 1028c72fcc34Sopenharmony_ci} 1029c72fcc34Sopenharmony_ci 1030c72fcc34Sopenharmony_ciint ssp_mn_set_params(struct intel_nhlt_params *nhlt, int m_div, int n_div) 1031c72fcc34Sopenharmony_ci{ 1032c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1033c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1034c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1035c72fcc34Sopenharmony_ci 1036c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1037c72fcc34Sopenharmony_ci return -EINVAL; 1038c72fcc34Sopenharmony_ci 1039c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_MN_DIVIDER_CONTROLS); 1040c72fcc34Sopenharmony_ci 1041c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].mn.m_div = m_div; 1042c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].mn.n_div = n_div; 1043c72fcc34Sopenharmony_ci 1044c72fcc34Sopenharmony_ci return 0; 1045c72fcc34Sopenharmony_ci} 1046c72fcc34Sopenharmony_ci 1047c72fcc34Sopenharmony_ciint ssp_clk_set_params(struct intel_nhlt_params *nhlt, int clock_warm_up, int mclk, int warm_up_ovr, 1048c72fcc34Sopenharmony_ci int clock_stop_delay, int keep_running, int clock_stop_ovr) 1049c72fcc34Sopenharmony_ci{ 1050c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1051c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1052c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1053c72fcc34Sopenharmony_ci 1054c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1055c72fcc34Sopenharmony_ci return -EINVAL; 1056c72fcc34Sopenharmony_ci 1057c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS); 1058c72fcc34Sopenharmony_ci 1059c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_warm_up = clock_warm_up; 1060c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.mclk = mclk; 1061c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.warm_up_ovr = warm_up_ovr; 1062c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_delay = clock_stop_delay; 1063c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.keep_running = keep_running; 1064c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].clk.clock_stop_ovr = clock_stop_ovr; 1065c72fcc34Sopenharmony_ci 1066c72fcc34Sopenharmony_ci return 0; 1067c72fcc34Sopenharmony_ci} 1068c72fcc34Sopenharmony_ci 1069c72fcc34Sopenharmony_ciint ssp_tr_start_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, 1070c72fcc34Sopenharmony_ci int bit_depth, int channel_map, int channel_config, 1071c72fcc34Sopenharmony_ci int interleaving_style, int number_of_channels, 1072c72fcc34Sopenharmony_ci int valid_bit_depth, int sample_type) 1073c72fcc34Sopenharmony_ci{ 1074c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp; 1075c72fcc34Sopenharmony_ci struct ssp_aux_config_tr *tr; 1076c72fcc34Sopenharmony_ci int di, hwi; 1077c72fcc34Sopenharmony_ci 1078c72fcc34Sopenharmony_ci ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1079c72fcc34Sopenharmony_ci di = ssp->ssp_count; 1080c72fcc34Sopenharmony_ci hwi = ssp->ssp_hw_config_count[di]; 1081c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1082c72fcc34Sopenharmony_ci return -EINVAL; 1083c72fcc34Sopenharmony_ci tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_start); 1084c72fcc34Sopenharmony_ci 1085c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_START); 1086c72fcc34Sopenharmony_ci 1087c72fcc34Sopenharmony_ci tr->sampling_frequency = sampling_frequency; 1088c72fcc34Sopenharmony_ci tr->bit_depth = bit_depth; 1089c72fcc34Sopenharmony_ci tr->channel_map = channel_map; 1090c72fcc34Sopenharmony_ci tr->channel_config = channel_config; 1091c72fcc34Sopenharmony_ci tr->interleaving_style = interleaving_style; 1092c72fcc34Sopenharmony_ci tr->number_of_channels = number_of_channels; 1093c72fcc34Sopenharmony_ci tr->valid_bit_depth = valid_bit_depth; 1094c72fcc34Sopenharmony_ci tr->sample_type = sample_type; 1095c72fcc34Sopenharmony_ci 1096c72fcc34Sopenharmony_ci return 0; 1097c72fcc34Sopenharmony_ci} 1098c72fcc34Sopenharmony_ci 1099c72fcc34Sopenharmony_ciint ssp_tr_stop_set_params(struct intel_nhlt_params *nhlt, int sampling_frequency, 1100c72fcc34Sopenharmony_ci int bit_depth, int channel_map, int channel_config, 1101c72fcc34Sopenharmony_ci int interleaving_style, int number_of_channels, 1102c72fcc34Sopenharmony_ci int valid_bit_depth, int sample_type) 1103c72fcc34Sopenharmony_ci{ 1104c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp; 1105c72fcc34Sopenharmony_ci struct ssp_aux_config_tr *tr; 1106c72fcc34Sopenharmony_ci int di, hwi; 1107c72fcc34Sopenharmony_ci 1108c72fcc34Sopenharmony_ci ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1109c72fcc34Sopenharmony_ci di = ssp->ssp_count; 1110c72fcc34Sopenharmony_ci hwi = ssp->ssp_hw_config_count[di]; 1111c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1112c72fcc34Sopenharmony_ci return -EINVAL; 1113c72fcc34Sopenharmony_ci tr = (struct ssp_aux_config_tr *)&(ssp->ssp_prm[di].aux_cfg[hwi].tr_stop); 1114c72fcc34Sopenharmony_ci 1115c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_TRANSMISSION_STOP); 1116c72fcc34Sopenharmony_ci 1117c72fcc34Sopenharmony_ci tr->sampling_frequency = sampling_frequency; 1118c72fcc34Sopenharmony_ci tr->bit_depth = bit_depth; 1119c72fcc34Sopenharmony_ci tr->channel_map = channel_map; 1120c72fcc34Sopenharmony_ci tr->channel_config = channel_config; 1121c72fcc34Sopenharmony_ci tr->interleaving_style = interleaving_style; 1122c72fcc34Sopenharmony_ci tr->number_of_channels = number_of_channels; 1123c72fcc34Sopenharmony_ci tr->valid_bit_depth = valid_bit_depth; 1124c72fcc34Sopenharmony_ci tr->sample_type = sample_type; 1125c72fcc34Sopenharmony_ci 1126c72fcc34Sopenharmony_ci return 0; 1127c72fcc34Sopenharmony_ci} 1128c72fcc34Sopenharmony_ci 1129c72fcc34Sopenharmony_ciint ssp_run_set_params(struct intel_nhlt_params *nhlt, int always_run) 1130c72fcc34Sopenharmony_ci{ 1131c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1132c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1133c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1134c72fcc34Sopenharmony_ci 1135c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1136c72fcc34Sopenharmony_ci return -EINVAL; 1137c72fcc34Sopenharmony_ci 1138c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_ALWAYS_RUNNING_MODE); 1139c72fcc34Sopenharmony_ci 1140c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].run.always_run = always_run; 1141c72fcc34Sopenharmony_ci 1142c72fcc34Sopenharmony_ci return 0; 1143c72fcc34Sopenharmony_ci} 1144c72fcc34Sopenharmony_ci 1145c72fcc34Sopenharmony_ciint ssp_sync_set_params(struct intel_nhlt_params *nhlt, int sync_denominator) 1146c72fcc34Sopenharmony_ci{ 1147c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1148c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1149c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1150c72fcc34Sopenharmony_ci 1151c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1152c72fcc34Sopenharmony_ci return -EINVAL; 1153c72fcc34Sopenharmony_ci 1154c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_SYNC_DATA); 1155c72fcc34Sopenharmony_ci 1156c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].sync.sync_denominator = sync_denominator; 1157c72fcc34Sopenharmony_ci 1158c72fcc34Sopenharmony_ci return 0; 1159c72fcc34Sopenharmony_ci} 1160c72fcc34Sopenharmony_ci 1161c72fcc34Sopenharmony_ciint ssp_node_set_params(struct intel_nhlt_params *nhlt, int node_id, int sampling_rate) 1162c72fcc34Sopenharmony_ci{ 1163c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1164c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1165c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1166c72fcc34Sopenharmony_ci int count; 1167c72fcc34Sopenharmony_ci 1168c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1169c72fcc34Sopenharmony_ci return -EINVAL; 1170c72fcc34Sopenharmony_ci 1171c72fcc34Sopenharmony_ci count = ssp->ssp_prm[di].aux_cfg[hwi].sync.count; 1172c72fcc34Sopenharmony_ci if (count > SSP_MAX_DAIS) 1173c72fcc34Sopenharmony_ci return -EINVAL; 1174c72fcc34Sopenharmony_ci 1175c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].node_id = node_id; 1176c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].sync.nodes[count].sampling_rate = sampling_rate; 1177c72fcc34Sopenharmony_ci 1178c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].sync.count++; 1179c72fcc34Sopenharmony_ci 1180c72fcc34Sopenharmony_ci return 0; 1181c72fcc34Sopenharmony_ci} 1182c72fcc34Sopenharmony_ci 1183c72fcc34Sopenharmony_ciint ssp_ext_set_params(struct intel_nhlt_params *nhlt, int mclk_policy_override, 1184c72fcc34Sopenharmony_ci int mclk_always_running, int mclk_starts_on_gtw_init, int mclk_starts_on_run, 1185c72fcc34Sopenharmony_ci int mclk_starts_on_pause, int mclk_stops_on_pause, int mclk_stops_on_reset, 1186c72fcc34Sopenharmony_ci int bclk_policy_override, int bclk_always_running, 1187c72fcc34Sopenharmony_ci int bclk_starts_on_gtw_init, int bclk_starts_on_run, 1188c72fcc34Sopenharmony_ci int bclk_starts_on_pause, int bclk_stops_on_pause, int bclk_stops_on_reset, 1189c72fcc34Sopenharmony_ci int sync_policy_override, int sync_always_running, 1190c72fcc34Sopenharmony_ci int sync_starts_on_gtw_init, int sync_starts_on_run, 1191c72fcc34Sopenharmony_ci int sync_starts_on_pause, int sync_stops_on_pause, int sync_stops_on_reset) 1192c72fcc34Sopenharmony_ci{ 1193c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1194c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1195c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1196c72fcc34Sopenharmony_ci 1197c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1198c72fcc34Sopenharmony_ci return -EINVAL; 1199c72fcc34Sopenharmony_ci 1200c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_DMA_CLK_CONTROLS_EXT); 1201c72fcc34Sopenharmony_ci 1202c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_policy_override = mclk_policy_override; 1203c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_always_running = mclk_always_running; 1204c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_gtw_init = mclk_starts_on_gtw_init; 1205c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_run = mclk_starts_on_run; 1206c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_starts_on_pause = mclk_starts_on_pause; 1207c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_pause = mclk_stops_on_pause; 1208c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.mclk_stops_on_reset = mclk_stops_on_reset; 1209c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_policy_override = bclk_policy_override; 1210c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_always_running = bclk_always_running; 1211c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_gtw_init = bclk_starts_on_gtw_init; 1212c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_run = bclk_starts_on_run; 1213c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_starts_on_pause = bclk_starts_on_pause; 1214c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_pause = bclk_stops_on_pause; 1215c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.bclk_stops_on_reset = bclk_stops_on_reset; 1216c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_policy_override = sync_policy_override; 1217c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_always_running = sync_always_running; 1218c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_gtw_init = sync_starts_on_gtw_init; 1219c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_run = sync_starts_on_run; 1220c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_starts_on_pause = sync_starts_on_pause; 1221c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_pause = sync_stops_on_pause; 1222c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].ext.sync_stops_on_reset = sync_stops_on_reset; 1223c72fcc34Sopenharmony_ci 1224c72fcc34Sopenharmony_ci return 0; 1225c72fcc34Sopenharmony_ci} 1226c72fcc34Sopenharmony_ci 1227c72fcc34Sopenharmony_ciint ssp_link_set_params(struct intel_nhlt_params *nhlt, int clock_source) 1228c72fcc34Sopenharmony_ci{ 1229c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp = (struct intel_ssp_params *)nhlt->ssp_params; 1230c72fcc34Sopenharmony_ci int di = ssp->ssp_count; 1231c72fcc34Sopenharmony_ci int hwi = ssp->ssp_hw_config_count[di]; 1232c72fcc34Sopenharmony_ci 1233c72fcc34Sopenharmony_ci if (di < 0 || hwi < 0) 1234c72fcc34Sopenharmony_ci return -EINVAL; 1235c72fcc34Sopenharmony_ci 1236c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].enabled |= BIT(SSP_LINK_CLK_SOURCE); 1237c72fcc34Sopenharmony_ci 1238c72fcc34Sopenharmony_ci ssp->ssp_prm[di].aux_cfg[hwi].link.clock_source = clock_source; 1239c72fcc34Sopenharmony_ci 1240c72fcc34Sopenharmony_ci return 0; 1241c72fcc34Sopenharmony_ci} 1242c72fcc34Sopenharmony_ci 1243c72fcc34Sopenharmony_ci/* init ssp parameters, should be called before parsing dais */ 1244c72fcc34Sopenharmony_ciint ssp_init_params(struct intel_nhlt_params *nhlt) 1245c72fcc34Sopenharmony_ci{ 1246c72fcc34Sopenharmony_ci struct intel_ssp_params *ssp; 1247c72fcc34Sopenharmony_ci int i, j; 1248c72fcc34Sopenharmony_ci 1249c72fcc34Sopenharmony_ci ssp = calloc(1, sizeof(struct intel_ssp_params)); 1250c72fcc34Sopenharmony_ci if (!ssp) 1251c72fcc34Sopenharmony_ci return -EINVAL; 1252c72fcc34Sopenharmony_ci 1253c72fcc34Sopenharmony_ci nhlt->ssp_params = ssp; 1254c72fcc34Sopenharmony_ci ssp->ssp_count = 0; 1255c72fcc34Sopenharmony_ci 1256c72fcc34Sopenharmony_ci for (i = 0; i < SSP_MAX_DAIS; i++) { 1257c72fcc34Sopenharmony_ci ssp->ssp_hw_config_count[i] = 0; 1258c72fcc34Sopenharmony_ci for (j = 0; j < SSP_MAX_HW_CONFIG; j++) 1259c72fcc34Sopenharmony_ci ssp->ssp_prm[i].aux_cfg[j].sync.count = 0; 1260c72fcc34Sopenharmony_ci } 1261c72fcc34Sopenharmony_ci 1262c72fcc34Sopenharmony_ci return 0; 1263c72fcc34Sopenharmony_ci} 1264