dai: intel: dmic: Move definitions of nhlt structures to a new file

Definitions of a configuration blob structures were separated from the main
drivers header file and moved to a dedicated file to improve code
readability. Removed unnecessary nhlt_pdm_fir_coeffs structure.
The nhlt_pdm_ctrl_cfg structure was extended with nhlt_pdm_ctrl_fir_cfg
and fir coefficients.

Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
This commit is contained in:
Adrian Warecki 2023-05-04 16:29:18 +02:00 committed by Anas Nashif
commit 81944c5c62
3 changed files with 129 additions and 61 deletions

View file

@ -133,56 +133,6 @@
#define DMA_HANDSHAKE_DMIC_CH0 0
#define DMA_HANDSHAKE_DMIC_CH1 1
/* For NHLT DMIC configuration parsing */
#define DMIC_HW_CONTROLLERS_MAX 4
#define DMIC_HW_FIFOS_MAX 2
struct nhlt_dmic_gateway_attributes {
uint32_t dw;
};
struct nhlt_dmic_ts_group {
uint32_t ts_group[4];
};
struct nhlt_dmic_clock_on_delay {
uint32_t clock_on_delay;
};
struct nhlt_dmic_channel_ctrl_mask {
uint8_t channel_ctrl_mask;
uint8_t clock_source;
uint16_t rsvd;
};
struct nhlt_pdm_ctrl_mask {
uint32_t pdm_ctrl_mask;
};
struct nhlt_pdm_ctrl_cfg {
uint32_t cic_control;
uint32_t cic_config;
uint32_t reserved0;
uint32_t mic_control;
uint32_t pdm_sdw_map;
uint32_t reuse_fir_from_pdm;
uint32_t reserved1[2];
};
struct nhlt_pdm_ctrl_fir_cfg {
uint32_t fir_control;
uint32_t fir_config;
int32_t dc_offset_left;
int32_t dc_offset_right;
int32_t out_gain_left;
int32_t out_gain_right;
uint32_t reserved[2];
};
struct nhlt_pdm_fir_coeffs {
int32_t fir_coeffs[0];
};
enum dai_dmic_frame_format {
DAI_DMIC_FRAME_S16_LE = 0,
DAI_DMIC_FRAME_S24_4LE,

View file

@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
#include <adsp_clk.h>
#include "dmic.h"
#include <dmic_regs.h>
#include "dmic_nhlt.h"
extern struct dai_dmic_global_shared dai_dmic_global;
@ -279,8 +280,8 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
struct nhlt_pdm_ctrl_cfg *pdm_cfg[DMIC_HW_CONTROLLERS_MAX];
struct nhlt_pdm_ctrl_fir_cfg *fir_cfg_a[DMIC_HW_CONTROLLERS_MAX];
struct nhlt_pdm_ctrl_fir_cfg *fir_cfg_b[DMIC_HW_CONTROLLERS_MAX];
struct nhlt_pdm_fir_coeffs *fir_a[DMIC_HW_CONTROLLERS_MAX] = {NULL};
struct nhlt_pdm_fir_coeffs *fir_b[DMIC_HW_CONTROLLERS_MAX];
const uint32_t *fir_a[DMIC_HW_CONTROLLERS_MAX] = {NULL};
const uint32_t *fir_b[DMIC_HW_CONTROLLERS_MAX];
struct nhlt_dmic_channel_ctrl_mask *dmic_cfg;
uint32_t out_control[DMIC_HW_FIFOS_MAX] = {0};
@ -320,7 +321,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
/* Skip not used headers */
p += sizeof(struct nhlt_dmic_gateway_attributes);
p += sizeof(struct nhlt_dmic_ts_group);
p += sizeof(struct nhlt_dmic_clock_on_delay);
p += sizeof(struct nhlt_dmic_global_config);
/* Channel_ctlr_mask bits indicate the FIFOs enabled*/
dmic_cfg = (struct nhlt_dmic_channel_ctrl_mask *)p;
@ -512,8 +513,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
}
/* FIR A */
fir_cfg_a[n] = (struct nhlt_pdm_ctrl_fir_cfg *)p;
p += sizeof(struct nhlt_pdm_ctrl_fir_cfg);
fir_cfg_a[n] = &pdm_cfg[n]->fir_config[0];
val = fir_cfg_a[n]->fir_config;
fir_length = FIELD_GET(FIR_CONFIG_FIR_LENGTH, val);
fir_length_a = fir_length + 1; /* Need for parsing */
@ -583,8 +583,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
}
/* FIR B */
fir_cfg_b[n] = (struct nhlt_pdm_ctrl_fir_cfg *)p;
p += sizeof(struct nhlt_pdm_ctrl_fir_cfg);
fir_cfg_b[n] = &pdm_cfg[n]->fir_config[1];
val = fir_cfg_b[n]->fir_config;
fir_length = FIELD_GET(FIR_CONFIG_FIR_LENGTH, val);
fir_length_b = fir_length + 1; /* Need for parsing */
@ -642,9 +641,9 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
/* Set up FIR coefficients RAM */
val = pdm_cfg[n]->reuse_fir_from_pdm;
if (val == 0) {
fir_a[n] = (struct nhlt_pdm_fir_coeffs *)p;
fir_a[n] = (uint32_t *)p;
p += sizeof(int32_t) * fir_length_a;
fir_b[n] = (struct nhlt_pdm_fir_coeffs *)p;
fir_b[n] = (uint32_t *)p;
p += sizeof(int32_t) * fir_length_b;
} else {
val--;
@ -669,14 +668,14 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf
p_clkdiv, p_mcic, p_mfira, fir_length_a);
for (i = 0; i < fir_length_a; i++)
dai_dmic_write(dmic,
coef_base_a[n] + (i << 2), fir_a[n]->fir_coeffs[i]);
coef_base_a[n] + (i << 2), fir_a[n][i]);
} else {
LOG_INF(
"dmic_set_config_nhlt(): clkdiv = %d, mcic = %d, mfir_b = %d, len = %d",
p_clkdiv, p_mcic, p_mfirb, fir_length_b);
for (i = 0; i < fir_length_b; i++)
dai_dmic_write(dmic,
coef_base_b[n] + (i << 2), fir_b[n]->fir_coeffs[i]);
coef_base_b[n] + (i << 2), fir_b[n][i]);
}
}

View file

@ -0,0 +1,119 @@
/* SPDX-License-Identifier: Apache-2.0 */
/*
* Copyright (c) 2023 Intel Corporation
*
* Author: Adrian Warecki <adrian.warecki@intel.com>
*/
#ifndef __INTEL_DAI_DRIVER_DMIC_NHLT_H__
#define __INTEL_DAI_DRIVER_DMIC_NHLT_H__
/* For NHLT DMIC configuration parsing */
#define DMIC_HW_CONTROLLERS_MAX 4
#define DMIC_HW_FIFOS_MAX 2
struct nhlt_dmic_gateway_attributes {
uint32_t dw;
};
/* Time-slot mappings */
struct nhlt_dmic_ts_group {
uint32_t ts_group[4];
};
/* Global configuration settings */
struct nhlt_dmic_global_config {
uint32_t clock_on_delay;
};
/* PDM channels to be programmed using data from channel_cfg array. */
struct nhlt_dmic_channel_ctrl_mask {
/* i'th bit = 1 means that configuration for PDM channel # i is provided. */
uint8_t channel_ctrl_mask;
uint8_t clock_source;
uint16_t rsvd;
};
/* Channel configuration, see PDM HW specification for details. */
struct nhlt_dmic_channel_config {
uint32_t out_control;
};
struct nhlt_dmic_config_blob {
struct nhlt_dmic_gateway_attributes gtw_attributes;
struct nhlt_dmic_ts_group time_slot;
struct nhlt_dmic_global_config global_config;
struct nhlt_dmic_channel_ctrl_mask ctrl_mask;
struct nhlt_dmic_channel_config channel_config[];
};
struct nhlt_pdm_ctrl_mask {
uint32_t pdm_ctrl_mask;
};
/* FIR configuration, see PDM HW specification for details.
*
* If there is only one PDM controller configuration passed, the other (missing) one is configured
* by the driver just by clearing CIC_CONTROL.SOFT_RESET bit.
*
* The driver needs to make sure that all mics are disabled before starting to program PDM
* controllers.
*/
struct nhlt_pdm_ctrl_fir_cfg {
uint32_t fir_control;
uint32_t fir_config;
int32_t dc_offset_left;
int32_t dc_offset_right;
int32_t out_gain_left;
int32_t out_gain_right;
uint32_t reserved[2];
};
/* PDM controller configuration, see PDM HW specification for details. */
struct nhlt_pdm_ctrl_cfg {
uint32_t cic_control;
uint32_t cic_config;
uint32_t reserved0;
uint32_t mic_control;
/* PDM SoundWire Map
*
* This field is used on platforms with SoundWire, otherwise ignored.
*/
uint32_t pdm_sdw_map;
/* Index of another nhlt_pdm_ctrl_cfg to be used as a source of FIR coefficients.
*
* The index is 1-based, value of 0 means that FIR coefficients array fir_coeffs is provided
* by this item.
* This is a very common case that the same FIR coefficients are used to program more than
* one PDM controller. In this case, fir_coeffs array may be provided in a single copy
* following nhlt_pdm_ctrl_cfg #0 and be reused by nhlt_pdm_ctrl_cfg #1 by setting
* reuse_fir_from_pdm to 1 (1-based index).
*/
uint32_t reuse_fir_from_pdm;
uint32_t reserved1[2];
/* FIR configurations */
struct nhlt_pdm_ctrl_fir_cfg fir_config[2];
/* Array of FIR coefficients, channel A goes first, then channel B.
*
* Actual size of the array depends on the number of active taps of the FIR filter for
* channel A plus the number of active taps of the FIR filter for channel B (see FIR_CONFIG)
* as well as on the form (packed/unpacked) of values.
*/
uint32_t fir_coeffs[];
};
/* Tag indicating that FIRs are in a packed 24-bit format.
*
* Size of a single coefficient is 20-bit. Coefficients may be sent in either unpacked form where
* each value takes one DWORD (32-bits) or in packed form where the array begins with
* (FIR_COEFFS_PACKED_TO_24_BITS) value to indicate packed form (unpacked coefficient has always
* most significant byte set to 0) followed by array of 24-bit values (in little endian form).
*/
#define FIR_COEFFS_PACKED_TO_24_BITS 0xFFFFFFFF
#endif /* __INTEL_DAI_DRIVER_DMIC_NHLT_H__ */