diff --git a/src/drivers/intel/dmic.c b/src/drivers/intel/dmic.c index 39172a74a..fff265cf9 100644 --- a/src/drivers/intel/dmic.c +++ b/src/drivers/intel/dmic.c @@ -134,7 +134,7 @@ static const uint32_t coef_base_a[4] = {PDM0_COEFFICIENT_A, PDM1_COEFFICIENT_A, static const uint32_t coef_base_b[4] = {PDM0_COEFFICIENT_B, PDM1_COEFFICIENT_B, PDM2_COEFFICIENT_B, PDM3_COEFFICIENT_B}; -/* Global configuration request for DMIC */ +/* Global configuration request for DMIC, need to use uncached address to access them */ static SHARED_DATA struct sof_ipc_dai_dmic_params *dmic_prm[DMIC_HW_FIFOS]; static SHARED_DATA int dmic_active_fifos; @@ -225,6 +225,7 @@ static enum task_state dmic_work(void *data) static void find_modes(struct dai *dai, struct decim_modes *modes, uint32_t fs, int di) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int clkdiv_min; int clkdiv_max; int clkdiv; @@ -256,37 +257,37 @@ static void find_modes(struct dai *dai, osr_min = DMIC_HIGH_RATE_OSR_MIN; /* Check for sane pdm clock, min 100 kHz, max ioclk/2 */ - if (dmic_prm[di]->pdmclk_max < DMIC_HW_PDM_CLK_MIN || - dmic_prm[di]->pdmclk_max > DMIC_HW_IOCLK / 2) { + if (uncached_dmic_prm[di]->pdmclk_max < DMIC_HW_PDM_CLK_MIN || + uncached_dmic_prm[di]->pdmclk_max > DMIC_HW_IOCLK / 2) { dai_err(dai, "find_modes(): pdm clock max not in range"); return; } - if (dmic_prm[di]->pdmclk_min < DMIC_HW_PDM_CLK_MIN || - dmic_prm[di]->pdmclk_min > dmic_prm[di]->pdmclk_max) { + if (uncached_dmic_prm[di]->pdmclk_min < DMIC_HW_PDM_CLK_MIN || + uncached_dmic_prm[di]->pdmclk_min > uncached_dmic_prm[di]->pdmclk_max) { dai_err(dai, "find_modes(): pdm clock min not in range"); return; } /* Check for sane duty cycle */ - if (dmic_prm[di]->duty_min > dmic_prm[di]->duty_max) { + if (uncached_dmic_prm[di]->duty_min > uncached_dmic_prm[di]->duty_max) { dai_err(dai, "find_modes(): duty cycle min > max"); return; } - if (dmic_prm[di]->duty_min < DMIC_HW_DUTY_MIN || - dmic_prm[di]->duty_min > DMIC_HW_DUTY_MAX) { + if (uncached_dmic_prm[di]->duty_min < DMIC_HW_DUTY_MIN || + uncached_dmic_prm[di]->duty_min > DMIC_HW_DUTY_MAX) { dai_err(dai, "find_modes(): pdm clock min not in range"); return; } - if (dmic_prm[di]->duty_max < DMIC_HW_DUTY_MIN || - dmic_prm[di]->duty_max > DMIC_HW_DUTY_MAX) { + if (uncached_dmic_prm[di]->duty_max < DMIC_HW_DUTY_MIN || + uncached_dmic_prm[di]->duty_max > DMIC_HW_DUTY_MAX) { dai_err(dai, "find_modes(): pdm clock max not in range"); return; } /* Min and max clock dividers */ - clkdiv_min = ceil_divide(DMIC_HW_IOCLK, dmic_prm[di]->pdmclk_max); + clkdiv_min = ceil_divide(DMIC_HW_IOCLK, uncached_dmic_prm[di]->pdmclk_max); clkdiv_min = MAX(clkdiv_min, DMIC_HW_CIC_DECIM_MIN); - clkdiv_max = DMIC_HW_IOCLK / dmic_prm[di]->pdmclk_min; + clkdiv_max = DMIC_HW_IOCLK / uncached_dmic_prm[di]->pdmclk_min; /* Loop possible clock dividers and check based on resulting * oversampling ratio that CIC and FIR decimation ratios are @@ -309,8 +310,8 @@ static void find_modes(struct dai *dai, * not exceed microphone specification. If exceed proceed to * next clkdiv. */ - if (osr < osr_min || du_min < dmic_prm[di]->duty_min || - du_max > dmic_prm[di]->duty_max) + if (osr < osr_min || du_min < uncached_dmic_prm[di]->duty_min || + du_max > uncached_dmic_prm[di]->duty_max) continue; /* Loop FIR decimation factors candidates. If the @@ -673,6 +674,7 @@ static int select_mode(struct dai *dai, static inline void ipm_helper1(int *ipm, int di) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int pdm[DMIC_HW_CONTROLLERS]; int i; @@ -681,8 +683,8 @@ static inline void ipm_helper1(int *ipm, int di) * this DAI. */ for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - if (dmic_prm[di]->pdm[i].enable_mic_a || - dmic_prm[di]->pdm[i].enable_mic_b) + if (uncached_dmic_prm[di]->pdm[i].enable_mic_a || + uncached_dmic_prm[di]->pdm[i].enable_mic_b) pdm[i] = 1; else pdm[i] = 0; @@ -702,6 +704,7 @@ static inline void ipm_helper1(int *ipm, int di) static inline void ipm_helper2(int source[], int *ipm, int di) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int pdm[DMIC_HW_CONTROLLERS]; int i; int n = 0; @@ -715,8 +718,8 @@ static inline void ipm_helper2(int source[], int *ipm, int di) * pdm controllers to be used for IPM configuration. */ for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - if (dmic_prm[di]->pdm[i].enable_mic_a || - dmic_prm[di]->pdm[i].enable_mic_b) { + if (uncached_dmic_prm[di]->pdm[i].enable_mic_a || + uncached_dmic_prm[di]->pdm[i].enable_mic_b) { pdm[i] = 1; source[n] = i; n++; @@ -739,6 +742,7 @@ static inline void ipm_helper2(int source[], int *ipm, int di) */ static int stereo_helper(int stereo[], int swap[]) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int cnt; int i; int swap_check; @@ -746,12 +750,12 @@ static int stereo_helper(int stereo[], int swap[]) for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { cnt = 0; - if (dmic_prm[0]->pdm[i].enable_mic_a || - dmic_prm[1]->pdm[i].enable_mic_a) + if (uncached_dmic_prm[0]->pdm[i].enable_mic_a || + uncached_dmic_prm[1]->pdm[i].enable_mic_a) cnt++; - if (dmic_prm[0]->pdm[i].enable_mic_b || - dmic_prm[1]->pdm[i].enable_mic_b) + if (uncached_dmic_prm[0]->pdm[i].enable_mic_b || + uncached_dmic_prm[1]->pdm[i].enable_mic_b) cnt++; /* Set stereo mode if both mic A anc B are enabled. */ @@ -759,12 +763,12 @@ static int stereo_helper(int stereo[], int swap[]) stereo[i] = cnt; /* Swap channels if only mic B is used for mono processing. */ - swap[i] = (dmic_prm[0]->pdm[i].enable_mic_b || - dmic_prm[1]->pdm[i].enable_mic_b) && !cnt; + swap[i] = (uncached_dmic_prm[0]->pdm[i].enable_mic_b || + uncached_dmic_prm[1]->pdm[i].enable_mic_b) && !cnt; /* Check that swap does not conflict with other DAI request */ - swap_check = dmic_prm[1]->pdm[i].enable_mic_a || - dmic_prm[0]->pdm[i].enable_mic_a; + swap_check = uncached_dmic_prm[1]->pdm[i].enable_mic_a || + uncached_dmic_prm[0]->pdm[i].enable_mic_a; if (swap_check && swap[i]) ret = -EINVAL; @@ -775,13 +779,14 @@ static int stereo_helper(int stereo[], int swap[]) static int configure_registers(struct dai *dai, struct dmic_configuration *cfg) { + struct sof_ipc_dai_dmic_params **prm_t = cache_to_uncache(&dmic_prm[0]); + int uncached_dmic_active_fifos = *cache_to_uncache(&dmic_active_fifos); int stereo[DMIC_HW_CONTROLLERS]; int swap[DMIC_HW_CONTROLLERS]; uint32_t val; uint32_t ref; int32_t ci; uint32_t cu; - int uncached_dmic_active_fifos = *cache_to_uncache(&dmic_active_fifos); int ipm; int of0; int of1; @@ -821,10 +826,10 @@ static int configure_registers(struct dai *dai, dai_info(dai, "configuring registers"); /* OUTCONTROL0 and OUTCONTROL1 */ - of0 = (dmic_prm[0]->fifo_bits == 32) ? 2 : 0; + of0 = (prm_t[0]->fifo_bits == 32) ? 2 : 0; #if DMIC_HW_FIFOS > 1 - of1 = (dmic_prm[1]->fifo_bits == 32) ? 2 : 0; + of1 = (prm_t[1]->fifo_bits == 32) ? 2 : 0; #else of1 = 0; #endif @@ -897,8 +902,8 @@ static int configure_registers(struct dai *dai, * for starting correct parts of the HW. */ for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - pdata->enable[i] = (dmic_prm[di]->pdm[i].enable_mic_b << 1) | - dmic_prm[di]->pdm[i].enable_mic_a; + pdata->enable[i] = (prm_t[di]->pdm[i].enable_mic_b << 1) | + prm_t[di]->pdm[i].enable_mic_a; } @@ -914,8 +919,8 @@ static int configure_registers(struct dai *dai, val = CIC_CONTROL_SOFT_RESET(soft_reset) | CIC_CONTROL_CIC_START_B(0) | CIC_CONTROL_CIC_START_A(0) | - CIC_CONTROL_MIC_B_POLARITY(dmic_prm[di]->pdm[i].polarity_mic_a) | - CIC_CONTROL_MIC_A_POLARITY(dmic_prm[di]->pdm[i].polarity_mic_b) | + CIC_CONTROL_MIC_B_POLARITY(prm_t[di]->pdm[i].polarity_mic_a) | + CIC_CONTROL_MIC_A_POLARITY(prm_t[di]->pdm[i].polarity_mic_b) | CIC_CONTROL_MIC_MUTE(cic_mute) | CIC_CONTROL_STEREO_MODE(stereo[i]); dai_write(dai, base[i] + CIC_CONTROL, val); @@ -930,12 +935,12 @@ static int configure_registers(struct dai *dai, * since the mono decimation is done with only left channel * processing active. */ - edge = dmic_prm[di]->pdm[i].clk_edge; + edge = prm_t[di]->pdm[i].clk_edge; if (swap[i]) edge = !edge; val = MIC_CONTROL_PDM_CLKDIV(cfg->clkdiv - 2) | - MIC_CONTROL_PDM_SKEW(dmic_prm[di]->pdm[i].skew) | + MIC_CONTROL_PDM_SKEW(prm_t[di]->pdm[i].skew) | MIC_CONTROL_CLK_EDGE(edge) | MIC_CONTROL_PDM_EN_B(0) | MIC_CONTROL_PDM_EN_A(0); @@ -1061,12 +1066,18 @@ static int configure_registers(struct dai *dai, static int dmic_get_hw_params(struct dai *dai, struct sof_ipc_stream_params *params, int dir) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int di = dai->index; - params->rate = dmic_prm[di]->fifo_fs; + if (!uncached_dmic_prm[di]) { + dai_err(dai, "dmic_get_hw_params(): dai %d not configured! &dmic_prm[di] 0x%p", + di, &uncached_dmic_prm[di]); + return -EINVAL; + } + params->rate = uncached_dmic_prm[di]->fifo_fs; params->buffer_fmt = 0; - switch (dmic_prm[di]->num_pdm_active) { + switch (uncached_dmic_prm[di]->num_pdm_active) { case 1: params->channels = 2; break; @@ -1078,7 +1089,7 @@ static int dmic_get_hw_params(struct dai *dai, return -EINVAL; } - switch (dmic_prm[di]->fifo_bits) { + switch (uncached_dmic_prm[di]->fifo_bits) { case 16: params->frame_fmt = SOF_IPC_FRAME_S16_LE; break; @@ -1095,6 +1106,7 @@ static int dmic_get_hw_params(struct dai *dai, static int dmic_set_config(struct dai *dai, struct sof_ipc_dai_config *config) { + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); struct dmic_pdata *dmic = dai_get_drvdata(dai); struct matched_modes modes_ab; struct dmic_configuration cfg; @@ -1153,36 +1165,41 @@ static int dmic_set_config(struct dai *dai, struct sof_ipc_dai_config *config) * the active controllers * "prm" is initialized with default params for all HW controllers */ - if (!dmic_prm[0]) { + if (!uncached_dmic_prm[0]) { size = sizeof(struct sof_ipc_dai_dmic_params); - dmic_prm[0] = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, - SOF_MEM_CAPS_RAM, + dmic_prm[0] = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, + 0, SOF_MEM_CAPS_RAM, DMIC_HW_FIFOS * size); - if (!dmic_prm[0]) { + /* write it back */ + uncached_dmic_prm[0] = dmic_prm[0]; + if (!uncached_dmic_prm[0]) { dai_err(dai, "dmic_set_config(): prm not initialized"); ret = -ENOMEM; goto out; } - for (i = 1; i < DMIC_HW_FIFOS; i++) + for (i = 1; i < DMIC_HW_FIFOS; i++) { dmic_prm[i] = (struct sof_ipc_dai_dmic_params *) - ((uint8_t *)dmic_prm[i - 1] + size); + ((uint8_t *)uncached_dmic_prm[i - 1] + size); + /* write it back */ + uncached_dmic_prm[i] = dmic_prm[i]; + } } /* Copy the new DMIC params header (all but not pdm[]) to persistent. * The last arrived request determines the parameters. */ - ret = memcpy_s(dmic_prm[di], sizeof(*dmic_prm[di]), &config->dmic, + ret = memcpy_s(uncached_dmic_prm[di], sizeof(*uncached_dmic_prm[di]), &config->dmic, offsetof(struct sof_ipc_dai_dmic_params, pdm)); assert(!ret); /* copy the pdm controller params from ipc */ for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - dmic_prm[di]->pdm[i].id = i; + uncached_dmic_prm[di]->pdm[i].id = i; for (j = 0; j < config->dmic.num_pdm_active; j++) { /* copy the pdm controller params id the id's match */ - if (dmic_prm[di]->pdm[i].id == config->dmic.pdm[j].id) { - ret = memcpy_s(&dmic_prm[di]->pdm[i], - sizeof(dmic_prm[di]->pdm[i]), + if (uncached_dmic_prm[di]->pdm[i].id == config->dmic.pdm[j].id) { + ret = memcpy_s(&uncached_dmic_prm[di]->pdm[i], + sizeof(uncached_dmic_prm[di]->pdm[i]), &config->dmic.pdm[j], sizeof( struct sof_ipc_dai_dmic_pdm_ctrl)); @@ -1194,13 +1211,13 @@ static int dmic_set_config(struct dai *dai, struct sof_ipc_dai_config *config) dai_info(dai, "dmic_set_config(), prm config->dmic.num_pdm_active = %u", config->dmic.num_pdm_active); dai_info(dai, "dmic_set_config(), prm pdmclk_min = %u, pdmclk_max = %u", - dmic_prm[di]->pdmclk_min, dmic_prm[di]->pdmclk_max); + uncached_dmic_prm[di]->pdmclk_min, uncached_dmic_prm[di]->pdmclk_max); dai_info(dai, "dmic_set_config(), prm duty_min = %u, duty_max = %u", - dmic_prm[di]->duty_min, dmic_prm[di]->duty_max); + uncached_dmic_prm[di]->duty_min, uncached_dmic_prm[di]->duty_max); dai_info(dai, "dmic_set_config(), prm fifo_fs = %u, fifo_bits = %u", - dmic_prm[di]->fifo_fs, dmic_prm[di]->fifo_bits); + uncached_dmic_prm[di]->fifo_fs, uncached_dmic_prm[di]->fifo_bits); - switch (dmic_prm[di]->fifo_bits) { + switch (uncached_dmic_prm[di]->fifo_bits) { case 0: case 16: case 32: @@ -1217,15 +1234,15 @@ static int dmic_set_config(struct dai *dai, struct sof_ipc_dai_config *config) * to use for FIR coefficient RAM write as well as the CIC and FIR * shift values. */ - find_modes(dai, &modes_a, dmic_prm[0]->fifo_fs, di); - if (modes_a.num_of_modes == 0 && dmic_prm[0]->fifo_fs > 0) { + find_modes(dai, &modes_a, uncached_dmic_prm[0]->fifo_fs, di); + if (modes_a.num_of_modes == 0 && uncached_dmic_prm[0]->fifo_fs > 0) { dai_err(dai, "dmic_set_config(): No modes found found for FIFO A"); ret = -EINVAL; goto out; } - find_modes(dai, &modes_b, dmic_prm[1]->fifo_fs, di); - if (modes_b.num_of_modes == 0 && dmic_prm[1]->fifo_fs > 0) { + find_modes(dai, &modes_b, uncached_dmic_prm[1]->fifo_fs, di); + if (modes_b.num_of_modes == 0 && uncached_dmic_prm[1]->fifo_fs > 0) { dai_err(dai, "dmic_set_config(): No modes found for FIFO B"); ret = -EINVAL; goto out; @@ -1272,8 +1289,9 @@ out: /* start the DMIC for capture */ static void dmic_start(struct dai *dai) { - struct dmic_pdata *dmic = dai_get_drvdata(dai); + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int *uncached_dmic_active_fifos = cache_to_uncache(&dmic_active_fifos); + struct dmic_pdata *dmic = dai_get_drvdata(dai); int i; int mic_a; int mic_b; @@ -1311,13 +1329,13 @@ static void dmic_start(struct dai *dai) for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { mic_a = dmic->enable[i] & 1; mic_b = (dmic->enable[i] & 2) >> 1; - if (dmic_prm[0]->fifo_fs > 0) + if (uncached_dmic_prm[0]->fifo_fs > 0) fir_a = (dmic->enable[i] > 0) ? 1 : 0; else fir_a = 0; #if DMIC_HW_FIFOS > 1 - if (dmic_prm[1]->fifo_fs > 0) + if (uncached_dmic_prm[1]->fifo_fs > 0) fir_b = (dmic->enable[i] > 0) ? 1 : 0; else fir_b = 0; @@ -1611,8 +1629,9 @@ static int dmic_probe(struct dai *dai) static int dmic_remove(struct dai *dai) { - struct dmic_pdata *dmic = dai_get_drvdata(dai); + struct sof_ipc_dai_dmic_params **uncached_dmic_prm = cache_to_uncache(&dmic_prm[0]); int uncached_dmic_active_fifos = *cache_to_uncache(&dmic_active_fifos); + struct dmic_pdata *dmic = dai_get_drvdata(dai); int i; dai_info(dai, "dmic_remove()"); @@ -1634,9 +1653,12 @@ static int dmic_remove(struct dai *dai) /* Disable DMIC power */ pm_runtime_put_sync(DMIC_POW, dai->index); - rfree(dmic_prm[0]); - for (i = 0; i < DMIC_HW_FIFOS; i++) + rfree(uncached_dmic_prm[0]); + for (i = 0; i < DMIC_HW_FIFOS; i++) { dmic_prm[i] = NULL; + /* write it back */ + uncached_dmic_prm[i] = dmic_prm[i]; + } return 0; }