Skip to content

Commit

Permalink
ALSA: asoc: core - add Digital Audio Interface (DAI) control functions.
Browse files Browse the repository at this point in the history
This patch adds several functions for DAI control and config
and replaces the current method of calling function pointers within
the DAI struct.

Signed-off-by: Liam Girdwood <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Jaroslav Kysela <[email protected]>
  • Loading branch information
Liam Girdwood authored and perexg committed Jul 10, 2008
1 parent 7e25740 commit 8c6529d
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 8 deletions.
21 changes: 21 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
struct snd_ac97_bus_ops *ops, int num);
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);

/* Digital Audio Interface clocking API.*/
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir);

int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div);

int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out);

/* Digital Audio interface formatting */
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);

int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots);

int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);

/* Digital Audio Interface mute */
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);

/*
*Controls
*/
Expand Down
140 changes: 132 additions & 8 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
else {
codec_dai->pop_wait = 0;
cancel_delayed_work(&socdev->delayed_work);
if (codec_dai->dai_ops.digital_mute)
codec_dai->dai_ops.digital_mute(codec_dai, 0);
snd_soc_dai_digital_mute(codec_dai, 0);
}
} else {
/* no delayed work - do we need to power up codec */
Expand All @@ -454,8 +453,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
SND_SOC_DAPM_STREAM_START);

snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
if (codec_dai->dai_ops.digital_mute)
codec_dai->dai_ops.digital_mute(codec_dai, 0);
snd_soc_dai_digital_mute(codec_dai, 0);

} else {
/* codec already powered - power on widgets */
Expand All @@ -467,8 +465,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
if (codec_dai->dai_ops.digital_mute)
codec_dai->dai_ops.digital_mute(codec_dai, 0);

snd_soc_dai_digital_mute(codec_dai, 0);
}
}

Expand Down Expand Up @@ -566,8 +564,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&pcm_mutex);

/* apply codec digital mute */
if (!codec->active && codec_dai->dai_ops.digital_mute)
codec_dai->dai_ops.digital_mute(codec_dai, 1);
if (!codec->active)
snd_soc_dai_digital_mute(codec_dai, 1);

/* free any machine hw params */
if (machine->ops && machine->ops->hw_free)
Expand Down Expand Up @@ -1703,6 +1701,132 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);

/**
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
* @dai: DAI
* @clk_id: DAI specific clock ID
* @freq: new clock frequency in Hz
* @dir: new clock direction - input/output.
*
* Configures the DAI master (MCLK) or system (SYSCLK) clocking.
*/
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
if (dai->dai_ops.set_sysclk)
return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);

/**
* snd_soc_dai_set_clkdiv - configure DAI clock dividers.
* @dai: DAI
* @clk_id: DAI specific clock divider ID
* @div: new clock divisor.
*
* Configures the clock dividers. This is used to derive the best DAI bit and
* frame clocks from the system or master clock. It's best to set the DAI bit
* and frame clocks as low as possible to save system power.
*/
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
if (dai->dai_ops.set_clkdiv)
return dai->dai_ops.set_clkdiv(dai, div_id, div);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);

/**
* snd_soc_dai_set_pll - configure DAI PLL.
* @dai: DAI
* @pll_id: DAI specific PLL ID
* @freq_in: PLL input clock frequency in Hz
* @freq_out: requested PLL output clock frequency in Hz
*
* Configures and enables PLL to generate output clock based on input clock.
*/
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
if (dai->dai_ops.set_pll)
return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);

/**
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI
* @clk_id: DAI specific clock ID
* @fmt: SND_SOC_DAIFMT_ format value.
*
* Configures the DAI hardware format and clocking.
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
if (dai->dai_ops.set_fmt)
return dai->dai_ops.set_fmt(dai, fmt);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);

/**
* snd_soc_dai_set_tdm_slot - configure DAI TDM.
* @dai: DAI
* @mask: DAI specific mask representing used slots.
* @slots: Number of slots in use.
*
* Configures a DAI for TDM operation. Both mask and slots are codec and DAI
* specific.
*/
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots)
{
if (dai->dai_ops.set_sysclk)
return dai->dai_ops.set_tdm_slot(dai, mask, slots);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);

/**
* snd_soc_dai_set_tristate - configure DAI system or master clock.
* @dai: DAI
* @tristate: tristate enable
*
* Tristates the DAI so that others can use it.
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
if (dai->dai_ops.set_sysclk)
return dai->dai_ops.set_tristate(dai, tristate);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);

/**
* snd_soc_dai_digital_mute - configure DAI system or master clock.
* @dai: DAI
* @mute: mute enable
*
* Mutes the DAI DAC.
*/
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
{
if (dai->dai_ops.digital_mute)
return dai->dai_ops.digital_mute(dai, mute);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);

static int __devinit snd_soc_init(void)
{
printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
Expand Down

0 comments on commit 8c6529d

Please sign in to comment.