[Sound-open-firmware] [PATCH] dai: config: Use a generic structure for DAI configuration

Liam Girdwood liam.r.girdwood at linux.intel.com
Mon Aug 21 21:34:36 CEST 2017


Use a generic structure containing common DAI settings for configuration.
This structure also contains a tail of DAI specific data that can also
be used by DAI drivers.

Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
---
 src/audio/dai.c                    | 31 +++++++--------
 src/drivers/ssp.c                  | 52 ++++++++++++-------------
 src/include/reef/audio/component.h |  7 ++--
 src/include/reef/dai.h             | 16 ++------
 src/include/reef/ipc.h             |  2 +-
 src/include/reef/ssp.h             |  1 +
 src/include/uapi/ipc.h             | 77 ++++++++++++++++++++++++--------------
 src/ipc/intel-ipc.c                | 31 ++++++---------
 src/ipc/ipc.c                      |  2 +-
 9 files changed, 110 insertions(+), 109 deletions(-)

diff --git a/src/audio/dai.c b/src/audio/dai.c
index 4464398..c89103d 100644
--- a/src/audio/dai.c
+++ b/src/audio/dai.c
@@ -544,26 +544,23 @@ static int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn)
 	return 0;
 }
 
-static int dai_config(struct comp_dev *dev, struct dai_config *dai_config)
+static int dai_config(struct comp_dev *dev, struct sof_ipc_dai_config *config)
 {
-	struct dai_data *dd = comp_get_drvdata(dev);
-
-	switch (dai_config->type) {
-	case DAI_TYPE_INTEL_SSP:
-		switch (dai_config->ssp->frame_width) {
-		case 16:
-			dd->sample_width = 2;
-			break;
-		case 17 ... 32:
-			dd->sample_width = 4;
-			break;
-		default:
-			trace_dai_error("eft");
-			return -EINVAL;
-		}
+	/* calc frame bytes */
+	switch (config->sample_valid_bits) {
+	case 16:
+		dev->frame_bytes = 2 * config->num_slots;
+		break;
+	case 17 ... 32:
+		dev->frame_bytes = 4 * config->num_slots;
 		break;
 	default:
-		dd->sample_width = 2;
+		break;
+	}
+
+	if (dev->frame_bytes == 0) {
+		trace_dai_error("de1");
+		return -EINVAL;
 	}
 
 	return 0;
diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c
index 2146f83..1a1000a 100644
--- a/src/drivers/ssp.c
+++ b/src/drivers/ssp.c
@@ -65,12 +65,12 @@ static int ssp_context_restore(struct dai *dai)
 }
 
 /* Digital Audio interface formatting */
-static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
+static inline int ssp_set_config(struct dai *dai,
+	struct sof_ipc_dai_config *config)
 {
 	struct ssp_pdata *ssp = dai_get_drvdata(dai);
-	struct sof_ipc_dai_ssp_params *params = &ssp->params;
 	uint32_t sscr0, sscr1, sspsp, sfifott, mdiv, bdiv;
-	uint32_t stop_size, phy_frame_size, data_size;
+	uint32_t stop_size, data_size;
 	int ret = 0;
 
 	spin_lock(&ssp->lock);
@@ -88,10 +88,15 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	sscr0 = 0;
 	sscr1 = 0;
 	sspsp = 0;
-	ssp->params = *dai_config->ssp;
+
+	ssp->config = *config;
+	ssp->params = config->ssp[0];
+
+	/* TODO: allow topology to define SSP clock type */
+	config->ssp[0].clk_id = SSP_CLK_EXT;
 
 	/* clock masters */
-	switch (params->format & SOF_DAI_FMT_MASTER_MASK) {
+	switch (config->format & SOF_DAI_FMT_MASTER_MASK) {
 	case SOF_DAI_FMT_CBM_CFM:
 		sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
 		break;
@@ -112,7 +117,7 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	}
 
 	/* clock signal polarity */
-	switch (params->format & SOF_DAI_FMT_INV_MASK) {
+	switch (config->format & SOF_DAI_FMT_INV_MASK) {
 	case SOF_DAI_FMT_NB_NF:
 		break;
 	case SOF_DAI_FMT_NB_IF:
@@ -129,7 +134,7 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	}
 
 	/* clock source */
-	switch (params->clk_id) {
+	switch (config->ssp[0].clk_id) {
 	case SSP_CLK_AUDIO:
 		sscr0 |= SSCR0_ACS;
 		break;
@@ -148,14 +153,14 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	}
 
 	/* BCLK is generated from MCLK - must be divisable */
-	if (params->mclk % params->bclk) {
+	if (config->mclk % config->bclk) {
 		trace_ssp_error("ec1");
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* divisor must be within SCR range */
-	mdiv = (params->mclk / params->bclk)- 1;
+	mdiv = (config->mclk / config->bclk)- 1;
 	if (mdiv > (SSCR0_SCR_MASK >> 8)) {
 		trace_ssp_error("ec2");
 		ret = -EINVAL;
@@ -166,23 +171,22 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	sscr0 |= SSCR0_SCR(mdiv);
 
 	/* calc frame width based on BCLK and rate - must be divisable */
-	if (params->bclk % params->fclk) {
+	if (config->bclk % config->fclk) {
 		trace_ssp_error("ec3");
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* must be enouch BCLKs for data */
-	bdiv = params->bclk / params->fclk;
-	if (bdiv < params->frame_width * params->num_slots) {
+	bdiv = config->bclk / config->fclk;
+	if (bdiv < config->sample_container_bits * config->num_slots) {
 		trace_ssp_error("ec4");
 		ret = -EINVAL;
 		goto out;
 	}
 
-	/* physical frame size must be <= 38 */
-	phy_frame_size = bdiv / params->num_slots;
-	if (phy_frame_size > 38) {
+	/* sample_container_bits must be <= 38 for SSP */
+	if (config->sample_container_bits > 38) {
 		trace_ssp_error("ec5");
 		ret = -EINVAL;
 		goto out;
@@ -190,14 +194,14 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 
 	trace_value(mdiv);
 	trace_value(bdiv);
-	trace_value(phy_frame_size);
 
 	/* format */
-	switch (params->format & SOF_DAI_FMT_FORMAT_MASK) {
+	switch (config->format & SOF_DAI_FMT_FORMAT_MASK) {
 	case SOF_DAI_FMT_I2S:
 
 		/* calculate dummy stop size and include dummy start */
-		stop_size = phy_frame_size - params->frame_width - 1;
+		stop_size = config->sample_container_bits -
+			(config->sample_valid_bits) - 1;
 		trace_value(stop_size);
 		if (stop_size > 3) {
 			trace_ssp_error("ec6");
@@ -207,9 +211,9 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 
 		sscr0 |= SSCR0_PSP;
 		sscr1 |= SSCR1_TRAIL;
-		sspsp |= SSPSP_SFRMWDTH(phy_frame_size);
+		sspsp |= SSPSP_SFRMWDTH(config->sample_container_bits);
 		/* subtract 1 for I2S start delay */
-		sspsp |= SSPSP_SFRMDLY((phy_frame_size - 1) * 2);
+		sspsp |= SSPSP_SFRMDLY((config->sample_container_bits - 1) * 2);
 		sspsp |= SSPSP_DMYSTRT(1);
 		sspsp |= SSPSP_DMYSTOP(stop_size);
 		break;
@@ -225,16 +229,12 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config)
 	}
 
 	/* sample data size on SSP FIFO */
-	switch (params->frame_width) {
+	switch (config->sample_valid_bits) {
 	case 16:	/* 2 * 16bit packed into 32bit FIFO */
-	case 24:	/* 1 * 24bit in 32bit FIFO (8 MSBs not used) */
-	case 32:	/* 1 * 32bit packed into 32bit FIFO */
 		data_size = 32;
 		break;
 	default:
-		trace_ssp_error("ec7");
-		ret = -EINVAL;
-		goto out;
+		data_size = config->sample_valid_bits;
 	}
 
 	if (data_size > 16)
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h
index a74395c..260fbda 100644
--- a/src/include/reef/audio/component.h
+++ b/src/include/reef/audio/component.h
@@ -122,7 +122,8 @@ struct comp_ops {
 	int (*preload)(struct comp_dev *dev);
 
 	/* set component audio stream paramters */
-	int (*dai_config)(struct comp_dev *dev, struct dai_config *dai_config);
+	int (*dai_config)(struct comp_dev *dev,
+		struct sof_ipc_dai_config *dai_config);
 
 	/* used to pass standard and bespoke commands (with data) to component */
 	int (*cmd)(struct comp_dev *dev, int cmd, void *data);
@@ -261,10 +262,10 @@ static inline int comp_reset(struct comp_dev *dev)
 
 /* DAI configuration - only mandatory for DAI components */
 static inline int comp_dai_config(struct comp_dev *dev,
-	struct dai_config *dai_config)
+	struct sof_ipc_dai_config *config)
 {
 	if (dev->drv->ops.dai_config)
-		return dev->drv->ops.dai_config(dev, dai_config);
+		return dev->drv->ops.dai_config(dev, config);
 	return 0;
 }
 
diff --git a/src/include/reef/dai.h b/src/include/reef/dai.h
index 258b016..75eabce 100644
--- a/src/include/reef/dai.h
+++ b/src/include/reef/dai.h
@@ -58,7 +58,7 @@ struct dai;
 
 /* DAI operations - all optional */
 struct dai_ops {
-	int (*set_config)(struct dai *dai, struct dai_config *dai_config);
+	int (*set_config)(struct dai *dai, struct sof_ipc_dai_config *config);
 	int (*trigger)(struct dai *dai, int cmd, int direction);
 	int (*pm_context_restore)(struct dai *dai);
 	int (*pm_context_store)(struct dai *dai);
@@ -78,15 +78,6 @@ enum dai_type {
 	DAI_TYPE_INTEL_DMIC,
 };
 
-/* DAI runtime hardware configuration */
-struct dai_config {
-	enum dai_type type;
-	union {
-		struct sof_ipc_dai_ssp_params *ssp;
-		struct sof_ipc_dai_hda_params *hda;
-		struct sof_ipc_dai_dmic_params *dmic;
-	};
-};
 
 struct dai_plat_fifo_data {
 	uint32_t offset;
@@ -126,9 +117,10 @@ struct dai *dai_get(uint32_t type, uint32_t index);
 	dai->plat_data.fifo[direction].offset
 
 /* Digital Audio interface formatting */
-static inline int dai_set_config(struct dai *dai, struct dai_config *dai_config)
+static inline int dai_set_config(struct dai *dai,
+	struct sof_ipc_dai_config *config)
 {
-	return dai->ops->set_config(dai, dai_config);
+	return dai->ops->set_config(dai, config);
 }
 
 /* Digital Audio interface formatting */
diff --git a/src/include/reef/ipc.h b/src/include/reef/ipc.h
index 96f2924..253f4f4 100644
--- a/src/include/reef/ipc.h
+++ b/src/include/reef/ipc.h
@@ -157,6 +157,6 @@ struct ipc_comp_dev *ipc_get_comp(struct ipc *ipc, uint32_t id);
 /*
  * Configure all DAI components attached to DAI.
  */
-int ipc_comp_dai_config(struct ipc *ipc, struct dai_config *config);
+int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config);
 
 #endif
diff --git a/src/include/reef/ssp.h b/src/include/reef/ssp.h
index 77d7b2e..7e557ed 100644
--- a/src/include/reef/ssp.h
+++ b/src/include/reef/ssp.h
@@ -153,6 +153,7 @@ struct ssp_pdata {
 	spinlock_t lock;
 	uint32_t state[2];		/* SSP_STATE_ for each direction */
 	completion_t drain_complete;
+	struct sof_ipc_dai_config config;
 	struct sof_ipc_dai_ssp_params params;
 };
 
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 19ee898..ddca551 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -99,10 +99,8 @@
 #define SOF_IPC_COMP_GET_SRC			SOF_CMD_TYPE(0x007)
 
 /* DAI messages */
-#define SOF_IPC_COMP_SSP_CONFIG			SOF_CMD_TYPE(0x000)
-#define SOF_IPC_COMP_HDA_CONFIG			SOF_CMD_TYPE(0x001)
-#define SOF_IPC_COMP_DMIC_CONFIG		SOF_CMD_TYPE(0x002)
-#define SOF_IPC_COMP_LOOPBACK			SOF_CMD_TYPE(0x003)
+#define SOF_IPC_DAI_CONFIG			SOF_CMD_TYPE(0x001)
+#define SOF_IPC_DAI_LOOPBACK			SOF_CMD_TYPE(0x002)
 
 /* stream */
 #define SOF_IPC_STREAM_PCM_PARAMS		SOF_CMD_TYPE(0x001)
@@ -193,37 +191,68 @@ struct sof_ipc_compound_hdr {
 #define SOF_DAI_FMT_INV_MASK		0x0f00
 #define SOF_DAI_FMT_MASTER_MASK		0xf000
 
+/* types of DAI */
+enum sof_ipc_dai_type {
+	SOF_DAI_INTEL_NONE = 0,
+	SOF_DAI_INTEL_SSP,
+	SOF_DAI_INTEL_DMIC,
+	SOF_DAI_INTEL_HDA,
+};
+
 /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */
 struct sof_ipc_dai_ssp_params {
 	struct sof_ipc_hdr hdr;
-	uint32_t mclk;
-	uint32_t bclk;
-	uint32_t fclk;
-	uint16_t ssp_id;
 	uint16_t mode;
-	uint16_t num_slots;
-	uint16_t frame_width;
 	uint16_t clk_id;
-	uint16_t format;	/* SOF_DAI_FMT_ */
-	uint16_t mclk_master;
 } __attribute__((packed));
 
 /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */
 struct sof_ipc_dai_hda_params {
 	struct sof_ipc_hdr hdr;
-	uint32_t hda_id;
-	uint32_t mclk;
 	/* TODO */
 } __attribute__((packed));
 
 /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */
 struct sof_ipc_dai_dmic_params {
 	struct sof_ipc_hdr hdr;
-	uint32_t dmic_id;
-	uint32_t mclk;
 	/* TODO */
 } __attribute__((packed));
 
+
+/* general purpose DAI configuration */
+struct sof_ipc_dai_config {
+	struct sof_ipc_hdr hdr;
+	enum sof_ipc_dai_type type;
+	uint32_t id;	/* physical number if more than 1 of this type */
+
+	/* physical protocol and clocking */
+	uint16_t format;	/* SOF_DAI_FMT_ */
+	uint16_t reserved;	/* alignment */
+	uint32_t mclk;	/* mclk frequency in Hz */
+	uint32_t bclk;	/* bclk frequency in Hz */
+	uint32_t fclk;	/* cclk frequency in Hz */
+
+	/* TDM */
+	uint32_t num_slots;
+	uint32_t rx_slot_mask;
+	uint32_t tx_slot_mask;
+
+	/* data */
+	uint16_t sample_valid_bits;
+	uint16_t sample_container_bits;
+
+	/* MCLK */
+	uint16_t mclk_always_run;
+	uint16_t mclk_master;
+
+	/* HW specific data */
+	union {
+		struct sof_ipc_dai_ssp_params ssp[0];
+		struct sof_ipc_dai_hda_params hda[0];
+		struct sof_ipc_dai_dmic_params dmic[0];
+	};
+};
+
 /*
  * Stream configuration.
  */
@@ -325,9 +354,11 @@ struct sof_ipc_stream_params {
 	enum sof_ipc_buffer_format buffer_fmt;
 	uint32_t rate;
 	uint32_t channels;
-	uint32_t sample_size;
+	uint32_t sample_valid_bytes;
+	uint32_t sample_container_bytes;
 	/* for notifying host period has completed - 0 means no period IRQ */
 	uint32_t host_period_bytes;
+	enum sof_ipc_chmap chmap[SOF_IPC_MAX_CHANNELS];	/* channel map */
 } __attribute__((packed));
 
 /* PCM params info - SOF_IPC_STREAM_PCM_PARAMS */
@@ -454,25 +485,13 @@ struct sof_ipc_buffer {
 	uint32_t size;		/* buffer size in bytes */
 } __attribute__((packed));
 
-/* types of DAI */
-enum sof_ipc_dai_type {
-	SOF_DAI_INTEL_NONE = 0,
-	SOF_DAI_INTEL_SSP,
-	SOF_DAI_INTEL_DMIC,
-	SOF_DAI_INTEL_HDA,
-};
 
 /* generic component config data */
 struct sof_ipc_comp_config {
-	uint32_t format;	/* data format */
-	uint32_t frames;	/* number of frames to process, 0 is variable */
-	uint32_t channels;	/* max number of channels */
-	uint32_t frame_size;	/* sample size in bytes */
 	uint32_t periods_sink;	/* 0 means variable */
 	uint32_t periods_source;	/* 0 means variable */
 	uint32_t preload_count;	/* how many periods to preload */
 	enum sof_ipc_frame frame_fmt;
-	enum sof_ipc_chmap chmap[SOF_IPC_MAX_CHANNELS];	/* channel map */
 } __attribute__((packed));
 
 /* generic host component */
diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c
index 2d73fbb..81b30b5 100644
--- a/src/ipc/intel-ipc.c
+++ b/src/ipc/intel-ipc.c
@@ -400,39 +400,32 @@ static int ipc_glb_stream_message(uint32_t header)
  * DAI IPC Operations.
  */
 
-static int ipc_dai_ssp_config(uint32_t header)
+static int ipc_dai_config(uint32_t header)
 {
-	struct sof_ipc_dai_ssp_params *ssp = _ipc->comp_data;
-	struct dai_config dai_config;
+	struct sof_ipc_dai_config *config = _ipc->comp_data;
 	struct dai *dai;
 	int ret;
 
 	trace_ipc("DsF");
 
-	/* TODO: set type in topology */
-	dai_config.type = DAI_TYPE_INTEL_SSP;
-	dai_config.ssp = ssp;
-
-	/* TODO: allow topology to define SSP clock type */
-	dai_config.ssp->clk_id = SSP_CLK_EXT;
-
 	/* get DAI */
-	dai = dai_get(SOF_DAI_INTEL_SSP, ssp->ssp_id);
+	dai = dai_get(config->type, config->id);
 	if (dai == NULL) {
 		trace_ipc_error("eDi");
-		trace_value(ssp->ssp_id);
+		trace_value(config->type);
+		trace_value(config->id);
 		return -ENODEV;
 	}
 
 	/* configure DAI */
-	ret = dai_set_config(dai, &dai_config);
+	ret = dai_set_config(dai, config);
 	if (ret < 0) {
 		trace_ipc_error("eDC");
 		return ret;
 	}
 
-	/* now send params to all components who use that DAI */
-	return ipc_comp_dai_config(_ipc, &dai_config);
+	/* now send params to all DAI components who use that physical DAI */
+	return ipc_comp_dai_config(_ipc, config);
 }
 
 static int ipc_glb_dai_message(uint32_t header)
@@ -440,12 +433,10 @@ static int ipc_glb_dai_message(uint32_t header)
 	uint32_t cmd = (header & SOF_CMD_TYPE_MASK) >> SOF_CMD_TYPE_SHIFT;
 
 	switch (cmd) {
-	case iCS(SOF_IPC_COMP_SSP_CONFIG):
-		return ipc_dai_ssp_config(header);
-	case iCS(SOF_IPC_COMP_LOOPBACK):
+	case iCS(SOF_IPC_DAI_CONFIG):
+		return ipc_dai_config(header);
+	case iCS(SOF_IPC_DAI_LOOPBACK):
 		//return ipc_comp_set_value(header, COMP_CMD_LOOPBACK);
-	case iCS(SOF_IPC_COMP_HDA_CONFIG):
-	case iCS(SOF_IPC_COMP_DMIC_CONFIG):
 	default:
 		trace_ipc_error("eDc");
 		trace_value(header);
diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c
index 530fee9..323468b 100644
--- a/src/ipc/ipc.c
+++ b/src/ipc/ipc.c
@@ -307,7 +307,7 @@ void ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id)
 	pipeline_complete(ipc_pipe->pipeline);
 }
 
-int ipc_comp_dai_config(struct ipc *ipc, struct dai_config *config)
+int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config)
 {
 	struct ipc_comp_dev *icd;
 	struct list_item *clist;
-- 
2.11.0



More information about the Sound-open-firmware mailing list