Skip to content

Commit

Permalink
ASoC: meson: axg-tdm: add continuous clock support
Browse files Browse the repository at this point in the history
Some devices may need the clocks running, even while paused.
Add support for this use case.

Signed-off-by: Jerome Brunet <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mark Brown <[email protected]>
  • Loading branch information
jbrun3t authored and broonie committed Apr 29, 2024
1 parent f949ed4 commit a5a8903
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
40 changes: 40 additions & 0 deletions sound/soc/meson/axg-tdm-formatter.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,46 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts)
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_free);

int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
unsigned int fmt)
{
int ret = 0;

if (fmt & SND_SOC_DAIFMT_CONT) {
/* Clock are already enabled - skipping */
if (ts->clk_enabled)
return 0;

ret = clk_prepare_enable(ts->iface->mclk);
if (ret)
return ret;

ret = clk_prepare_enable(ts->iface->sclk);
if (ret)
goto err_sclk;

ret = clk_prepare_enable(ts->iface->lrclk);
if (ret)
goto err_lrclk;

ts->clk_enabled = true;
return 0;
}

/* Clocks are already disabled - skipping */
if (!ts->clk_enabled)
return 0;

clk_disable_unprepare(ts->iface->lrclk);
err_lrclk:
clk_disable_unprepare(ts->iface->sclk);
err_sclk:
clk_disable_unprepare(ts->iface->mclk);
ts->clk_enabled = false;
return ret;
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_set_cont_clocks);

MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver");
MODULE_AUTHOR("Jerome Brunet <[email protected]>");
MODULE_LICENSE("GPL v2");
16 changes: 15 additions & 1 deletion sound/soc/meson/axg-tdm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai);
struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
int ret;

switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
Expand Down Expand Up @@ -346,7 +347,19 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
return ret;
}

return 0;
ret = axg_tdm_stream_set_cont_clocks(ts, iface->fmt);
if (ret)
dev_err(dai->dev, "failed to apply continuous clock setting\n");

return ret;
}

static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);

return axg_tdm_stream_set_cont_clocks(ts, 0);
}

static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
Expand Down Expand Up @@ -417,6 +430,7 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
.set_fmt = axg_tdm_iface_set_fmt,
.startup = axg_tdm_iface_startup,
.hw_params = axg_tdm_iface_hw_params,
.hw_free = axg_tdm_iface_hw_free,
.trigger = axg_tdm_iface_trigger,
};

Expand Down
5 changes: 5 additions & 0 deletions sound/soc/meson/axg-tdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,17 @@ struct axg_tdm_stream {
unsigned int physical_width;
u32 *mask;
bool ready;

/* For continuous clock tracking */
bool clk_enabled;
};

struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
void axg_tdm_stream_free(struct axg_tdm_stream *ts);
int axg_tdm_stream_start(struct axg_tdm_stream *ts);
void axg_tdm_stream_stop(struct axg_tdm_stream *ts);
int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
unsigned int fmt);

static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
{
Expand Down

0 comments on commit a5a8903

Please sign in to comment.