diff --git a/src/drivers/intel/cavs/alh.c b/src/drivers/intel/cavs/alh.c index 9fa2ad3f5467..21a62916ffbb 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,35 @@ 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); + 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; } /* 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); + + params->rate = alh->params.rate; + 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 +79,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 +101,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__ */ 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);