Skip to content

Commit 6d0c1f7

Browse files
committed
Merge series "ASoC: SOF: Intel: add flags to turn on SSP clocks early" from Pierre-Louis Bossart <[email protected]>:
With the chip shortage, some GeminiLake Intel-based designs were respun and now rely on codecs that need the SSP bit clock turned on in the hw_params stage, not the trigger stage. This patchset mirrors the flags added in the SOF DAI_CONFIG IPC, and sets the flags when this capability is indicated as necessary in the topology files where the SSP configuration is stored. We initially considered a more generic solution with an on-demand SSP clock activation using the common clock framework. This would be a more elegant solution indeed, but it would have required more intrusive changes that would conflict with the SOF multi-client support (in-development), and more backport hassles on product branches. The on-demand activation of clocks is still a desired feature that will be enabled at a later point. Bard Liao (1): ASoC: SOF: dai-intel: add SOF_DAI_INTEL_SSP_CLKCTRL_MCLK/BCLK_ES bits Pierre-Louis Bossart (4): ASoC: SOF: dai: mirror group_id definition added in firmware ASoC: SOF: dai: include new flags for DAI_CONFIG ASoC: SOF: Intel: hda: add new flags for DAI_CONFIG ASoC: SOF: Intel: hda-dai: improve SSP DAI handling for dynamic pipelines include/sound/sof/dai-intel.h | 4 ++ include/sound/sof/dai.h | 10 ++++- sound/soc/sof/intel/hda-dai.c | 82 ++++++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda.c | 6 +++ sound/soc/sof/sof-audio.c | 4 ++ 5 files changed, 103 insertions(+), 3 deletions(-) -- 2.25.1
2 parents 84a9672 + 84e3cfd commit 6d0c1f7

File tree

5 files changed

+103
-3
lines changed

5 files changed

+103
-3
lines changed

include/sound/sof/dai-intel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
4848
#define SOF_DAI_INTEL_SSP_CLKCTRL_FS_KA BIT(4)
4949
/* bclk idle */
5050
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5)
51+
/* mclk early start */
52+
#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES BIT(6)
53+
/* bclk early start */
54+
#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES BIT(7)
5155

5256
/* DMIC max. four controllers for eight microphone channels */
5357
#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4

include/sound/sof/dai.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@
5050
#define SOF_DAI_FMT_INV_MASK 0x0f00
5151
#define SOF_DAI_FMT_CLOCK_PROVIDER_MASK 0xf000
5252

53+
/* DAI_CONFIG flags */
54+
#define SOF_DAI_CONFIG_FLAGS_MASK 0x3
55+
#define SOF_DAI_CONFIG_FLAGS_NONE (0 << 0) /**< DAI_CONFIG sent without stage information */
56+
#define SOF_DAI_CONFIG_FLAGS_HW_PARAMS (1 << 0) /**< DAI_CONFIG sent during hw_params stage */
57+
#define SOF_DAI_CONFIG_FLAGS_HW_FREE (2 << 0) /**< DAI_CONFIG sent during hw_free stage */
58+
#define SOF_DAI_CONFIG_FLAGS_RFU (3 << 0) /**< not used, reserved for future use */
59+
5360
/** \brief Types of DAI */
5461
enum sof_ipc_dai_type {
5562
SOF_DAI_INTEL_NONE = 0, /**< None */
@@ -69,7 +76,8 @@ struct sof_ipc_dai_config {
6976

7077
/* physical protocol and clocking */
7178
uint16_t format; /**< SOF_DAI_FMT_ */
72-
uint16_t reserved16; /**< alignment */
79+
uint8_t group_id; /**< group ID, 0 means no group (ABI 3.17) */
80+
uint8_t flags; /**< SOF_DAI_CONFIG_FLAGS_ (ABI 3.19) */
7381

7482
/* reserved for future use */
7583
uint32_t reserved[8];

sound/soc/sof/intel/hda-dai.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,11 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = {
440440

441441
#endif
442442

443+
/* only one flag used so far to harden hw_params/hw_free/trigger/prepare */
444+
struct ssp_dai_dma_data {
445+
bool setup;
446+
};
447+
443448
static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
444449
bool setup)
445450
{
@@ -469,22 +474,95 @@ static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd
469474
return hda_ctrl_dai_widget_free(w);
470475
}
471476

477+
static int ssp_dai_startup(struct snd_pcm_substream *substream,
478+
struct snd_soc_dai *dai)
479+
{
480+
struct ssp_dai_dma_data *dma_data;
481+
482+
dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
483+
if (!dma_data)
484+
return -ENOMEM;
485+
486+
snd_soc_dai_set_dma_data(dai, substream, dma_data);
487+
488+
return 0;
489+
}
490+
491+
static int ssp_dai_setup(struct snd_pcm_substream *substream,
492+
struct snd_soc_dai *dai,
493+
bool setup)
494+
{
495+
struct ssp_dai_dma_data *dma_data;
496+
int ret = 0;
497+
498+
dma_data = snd_soc_dai_get_dma_data(dai, substream);
499+
if (!dma_data) {
500+
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
501+
return -EIO;
502+
}
503+
504+
if (dma_data->setup != setup) {
505+
ret = ssp_dai_setup_or_free(substream, dai, setup);
506+
if (!ret)
507+
dma_data->setup = setup;
508+
}
509+
return ret;
510+
}
511+
472512
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
473513
struct snd_pcm_hw_params *params,
474514
struct snd_soc_dai *dai)
475515
{
476-
return ssp_dai_setup_or_free(substream, dai, true);
516+
/* params are ignored for now */
517+
return ssp_dai_setup(substream, dai, true);
518+
}
519+
520+
static int ssp_dai_prepare(struct snd_pcm_substream *substream,
521+
struct snd_soc_dai *dai)
522+
{
523+
/*
524+
* the SSP will only be reconfigured during resume operations and
525+
* not in case of xruns
526+
*/
527+
return ssp_dai_setup(substream, dai, true);
528+
}
529+
530+
static int ssp_dai_trigger(struct snd_pcm_substream *substream,
531+
int cmd, struct snd_soc_dai *dai)
532+
{
533+
if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
534+
return 0;
535+
536+
return ssp_dai_setup(substream, dai, false);
477537
}
478538

479539
static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
480540
struct snd_soc_dai *dai)
481541
{
482-
return ssp_dai_setup_or_free(substream, dai, false);
542+
return ssp_dai_setup(substream, dai, false);
543+
}
544+
545+
static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
546+
struct snd_soc_dai *dai)
547+
{
548+
struct ssp_dai_dma_data *dma_data;
549+
550+
dma_data = snd_soc_dai_get_dma_data(dai, substream);
551+
if (!dma_data) {
552+
dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
553+
return;
554+
}
555+
snd_soc_dai_set_dma_data(dai, substream, NULL);
556+
kfree(dma_data);
483557
}
484558

485559
static const struct snd_soc_dai_ops ssp_dai_ops = {
560+
.startup = ssp_dai_startup,
486561
.hw_params = ssp_dai_hw_params,
562+
.prepare = ssp_dai_prepare,
563+
.trigger = ssp_dai_trigger,
487564
.hw_free = ssp_dai_hw_free,
565+
.shutdown = ssp_dai_shutdown,
488566
};
489567

490568
/*

sound/soc/sof/intel/hda.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
7171
return ret;
7272
}
7373

74+
/* set HW_PARAMS flag */
75+
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_PARAMS);
76+
7477
/* send DAI_CONFIG IPC */
7578
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
7679
&reply, sizeof(reply));
@@ -107,6 +110,9 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
107110

108111
config = &sof_dai->dai_config[sof_dai->current_config];
109112

113+
/* set HW_FREE flag */
114+
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_FREE);
115+
110116
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
111117
&reply, sizeof(reply));
112118
if (ret < 0)

sound/soc/sof/sof-audio.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// Author: Ranjani Sridharan <[email protected]>
99
//
1010

11+
#include <linux/bitfield.h>
1112
#include "sof-audio.h"
1213
#include "ops.h"
1314

@@ -55,6 +56,9 @@ static int sof_dai_config_setup(struct snd_sof_dev *sdev, struct snd_sof_dai *da
5556
return -EINVAL;
5657
}
5758

59+
/* set NONE flag to clear all previous settings */
60+
config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_NONE);
61+
5862
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
5963
&reply, sizeof(reply));
6064

0 commit comments

Comments
 (0)