From b6ea2ec78eeecc069d7f3ade67d12c6066ebf3cb Mon Sep 17 00:00:00 2001 From: Slawomir Blauciak Date: Fri, 27 Mar 2020 09:50:59 +0100 Subject: [PATCH 1/2] alh: obtain hw params from ipc config This allows the firmware to become aware of the programmed format on ALH DAIs. The change is backwards compatible, in-case of ABI mismatch, the data will be filled with 0s, which is consistent with previous values. This change is required in the case of pipelines, that contain components capable of modifying the parameters of a stream, for example (de)mux. Signed-off-by: Slawomir Blauciak --- src/drivers/intel/cavs/alh.c | 41 +++++++++++++++++++++++++++++++---- src/include/ipc/dai-intel.h | 4 +++- src/include/sof/drivers/alh.h | 5 +++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/drivers/intel/cavs/alh.c b/src/drivers/intel/cavs/alh.c index 9fa2ad3f5467..2f20cdc34bc3 100644 --- a/src/drivers/intel/cavs/alh.c +++ b/src/drivers/intel/cavs/alh.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -29,21 +30,37 @@ static int alh_trigger(struct dai *dai, int cmd, int direction) static int alh_set_config(struct dai *dai, struct sof_ipc_dai_config *config) { + struct alh_pdata *alh = dai_get_drvdata(dai); + dai_info(dai, "alh_set_config() config->format = 0x%4x", config->format); + alh->params = config->alh; + return 0; } /* get ALH hw params */ static int alh_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) + struct sof_ipc_stream_params *params, int dir) { + struct alh_pdata *alh = dai_get_drvdata(dai); + + /* + * ALH config is sent multiple times, only the first batch contains + * the stream format + */ + if (alh->params.rate) + params->rate = alh->params.rate; + + if (alh->params.channels) + params->channels = alh->params.channels; + /* 0 means variable */ - params->rate = 0; - params->channels = 0; params->buffer_fmt = 0; - params->frame_fmt = 0; + + /* FIFO format is static */ + params->frame_fmt = SOF_IPC_FRAME_S32_LE; return 0; } @@ -64,8 +81,21 @@ static int alh_context_restore(struct dai *dai) static int alh_probe(struct dai *dai) { + struct alh_pdata *alh; + dai_info(dai, "alh_probe()"); + if (dai_get_drvdata(dai)) + return -EEXIST; + + alh = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, + sizeof(*alh)); + if (!alh) { + dai_err(dai, "ssp_probe() error: alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, alh); + return 0; } @@ -73,6 +103,9 @@ static int alh_remove(struct dai *dai) { dai_info(dai, "alh_remove()"); + rfree(dai_get_drvdata(dai)); + dai_set_drvdata(dai, NULL); + return 0; } diff --git a/src/include/ipc/dai-intel.h b/src/include/ipc/dai-intel.h index e57afd09d1c6..dce99382ba59 100644 --- a/src/include/ipc/dai-intel.h +++ b/src/include/ipc/dai-intel.h @@ -99,9 +99,11 @@ struct sof_ipc_dai_hda_params { struct sof_ipc_dai_alh_params { uint32_t reserved0; uint32_t stream_id; + uint32_t rate; + uint32_t channels; /* reserved for future use */ - uint32_t reserved[15]; + uint32_t reserved[13]; } __attribute__((packed)); /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */ diff --git a/src/include/sof/drivers/alh.h b/src/include/sof/drivers/alh.h index 189463bf1306..48a6d6b6c630 100644 --- a/src/include/sof/drivers/alh.h +++ b/src/include/sof/drivers/alh.h @@ -7,9 +7,14 @@ #ifndef __SOF_DRIVERS_ALH__ #define __SOF_DRIVERS_ALH__ +#include #include #include +struct alh_pdata { + struct sof_ipc_dai_alh_params params; +}; + extern const struct dai_driver alh_driver; #endif /* __SOF_DRIVERS_ALH__ */ From 5b43007e29ea3e8550381635b07fa01bc72a41a0 Mon Sep 17 00:00:00 2001 From: Slawomir Blauciak Date: Tue, 31 Mar 2020 12:27:46 +0200 Subject: [PATCH 2/2] dai: provide additional description of dai private data This provides basic guidelines to clear up how to allocate and use DAI private data. Signed-off-by: Slawomir Blauciak --- src/drivers/intel/cavs/alh.c | 18 ++++++++---------- src/include/sof/lib/dai.h | 7 +++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/drivers/intel/cavs/alh.c b/src/drivers/intel/cavs/alh.c index 2f20cdc34bc3..21a62916ffbb 100644 --- a/src/drivers/intel/cavs/alh.c +++ b/src/drivers/intel/cavs/alh.c @@ -35,7 +35,12 @@ static int alh_set_config(struct dai *dai, struct sof_ipc_dai_config *config) dai_info(dai, "alh_set_config() config->format = 0x%4x", config->format); - alh->params = config->alh; + if (config->alh.channels || config->alh.rate) { + alh->params.channels = config->alh.channels; + alh->params.rate = config->alh.rate; + } + + alh->params.stream_id = config->alh.stream_id; return 0; } @@ -46,15 +51,8 @@ static int alh_get_hw_params(struct dai *dai, { struct alh_pdata *alh = dai_get_drvdata(dai); - /* - * ALH config is sent multiple times, only the first batch contains - * the stream format - */ - if (alh->params.rate) - params->rate = alh->params.rate; - - if (alh->params.channels) - params->channels = alh->params.channels; + params->rate = alh->params.rate; + params->channels = alh->params.channels; /* 0 means variable */ params->buffer_fmt = 0; diff --git a/src/include/sof/lib/dai.h b/src/include/sof/lib/dai.h index db993eb33aea..9878961b0886 100644 --- a/src/include/sof/lib/dai.h +++ b/src/include/sof/lib/dai.h @@ -60,6 +60,13 @@ struct sof_ipc_stream_params; /** * \brief DAI operations - all optional + * + * DAI drivers may allocate private data, + * which can be set with 'dai_set_drvdata' and retrieved with 'dai_get_drvdata'. + * If a single DAI instance can have multiple DMA links and/or there is + * some other possibility of the same instance being used in multiple + * contexts at the same time, the private data should be allocated + * with the SOF_MEM_FLAG_SHARED flag. */ struct dai_ops { int (*set_config)(struct dai *dai, struct sof_ipc_dai_config *config);