summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c336
1 files changed, 47 insertions, 289 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1486fb2eb921..06697b2d96b1 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -165,9 +165,10 @@ static void soc_init_component_debugfs(struct snd_soc_component *component)
component->card->debugfs_card_root);
}
- if (!component->debugfs_root) {
+ if (IS_ERR(component->debugfs_root)) {
dev_warn(component->dev,
- "ASoC: Failed to create component debugfs directory\n");
+ "ASoC: Failed to create component debugfs directory: %ld\n",
+ PTR_ERR(component->debugfs_root));
return;
}
@@ -219,18 +220,21 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
card->debugfs_card_root = debugfs_create_dir(card->name,
snd_soc_debugfs_root);
- if (!card->debugfs_card_root) {
+ if (IS_ERR(card->debugfs_card_root)) {
dev_warn(card->dev,
- "ASoC: Failed to create card debugfs directory\n");
+ "ASoC: Failed to create card debugfs directory: %ld\n",
+ PTR_ERR(card->debugfs_card_root));
+ card->debugfs_card_root = NULL;
return;
}
card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644,
card->debugfs_card_root,
&card->pop_time);
- if (!card->debugfs_pop_time)
+ if (IS_ERR(card->debugfs_pop_time))
dev_warn(card->dev,
- "ASoC: Failed to create pop time debugfs file\n");
+ "ASoC: Failed to create pop time debugfs file: %ld\n",
+ PTR_ERR(card->debugfs_pop_time));
}
static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
@@ -483,10 +487,9 @@ int snd_soc_suspend(struct device *dev)
continue;
for_each_rtd_codec_dai(rtd, i, dai) {
- struct snd_soc_dai_driver *drv = dai->driver;
-
- if (drv->ops->digital_mute && dai->playback_active)
- drv->ops->digital_mute(dai, 1);
+ if (dai->playback_active)
+ snd_soc_dai_digital_mute(dai, 1,
+ SNDRV_PCM_STREAM_PLAYBACK);
}
}
@@ -507,8 +510,8 @@ int snd_soc_suspend(struct device *dev)
if (rtd->dai_link->ignore_suspend)
continue;
- if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control)
- cpu_dai->driver->suspend(cpu_dai);
+ if (!cpu_dai->driver->bus_control)
+ snd_soc_dai_suspend(cpu_dai);
}
/* close any waiting streams */
@@ -580,8 +583,8 @@ int snd_soc_suspend(struct device *dev)
if (rtd->dai_link->ignore_suspend)
continue;
- if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control)
- cpu_dai->driver->suspend(cpu_dai);
+ if (cpu_dai->driver->bus_control)
+ snd_soc_dai_suspend(cpu_dai);
/* deactivate pins to sleep state */
pinctrl_pm_select_sleep_state(cpu_dai->dev);
@@ -627,8 +630,8 @@ static void soc_resume_deferred(struct work_struct *work)
if (rtd->dai_link->ignore_suspend)
continue;
- if (cpu_dai->driver->resume && cpu_dai->driver->bus_control)
- cpu_dai->driver->resume(cpu_dai);
+ if (cpu_dai->driver->bus_control)
+ snd_soc_dai_resume(cpu_dai);
}
for_each_card_components(card, component) {
@@ -661,10 +664,9 @@ static void soc_resume_deferred(struct work_struct *work)
continue;
for_each_rtd_codec_dai(rtd, i, dai) {
- struct snd_soc_dai_driver *drv = dai->driver;
-
- if (drv->ops->digital_mute && dai->playback_active)
- drv->ops->digital_mute(dai, 0);
+ if (dai->playback_active)
+ snd_soc_dai_digital_mute(dai, 0,
+ SNDRV_PCM_STREAM_PLAYBACK);
}
}
@@ -674,8 +676,8 @@ static void soc_resume_deferred(struct work_struct *work)
if (rtd->dai_link->ignore_suspend)
continue;
- if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control)
- cpu_dai->driver->resume(cpu_dai);
+ if (!cpu_dai->driver->bus_control)
+ snd_soc_dai_resume(cpu_dai);
}
if (card->resume_post)
@@ -988,13 +990,12 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
dai->driver->remove_order != order)
return;
- if (dai->driver->remove) {
- err = dai->driver->remove(dai);
- if (err < 0)
- dev_err(dai->dev,
- "ASoC: failed to remove %s: %d\n",
- dai->name, err);
- }
+ err = snd_soc_dai_remove(dai);
+ if (err < 0)
+ dev_err(dai->dev,
+ "ASoC: failed to remove %s: %d\n",
+ dai->name, err);
+
dai->probed = 0;
}
@@ -1430,18 +1431,17 @@ static int soc_probe_link_components(struct snd_soc_card *card,
static int soc_probe_dai(struct snd_soc_dai *dai, int order)
{
+ int ret;
+
if (dai->probed ||
dai->driver->probe_order != order)
return 0;
- if (dai->driver->probe) {
- int ret = dai->driver->probe(dai);
-
- if (ret < 0) {
- dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n",
- dai->name, ret);
- return ret;
- }
+ ret = snd_soc_dai_probe(dai);
+ if (ret < 0) {
+ dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n",
+ dai->name, ret);
+ return ret;
}
dai->probed = 1;
@@ -1546,15 +1546,16 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
num = rtd->dai_link->id;
}
- if (cpu_dai->driver->compress_new) {
- /* create compress_device" */
- ret = cpu_dai->driver->compress_new(rtd, num);
- if (ret < 0) {
+ /* create compress_device if possible */
+ ret = snd_soc_dai_compress_new(cpu_dai, rtd, num);
+ if (ret != -ENOTSUPP) {
+ if (ret < 0)
dev_err(card->dev, "ASoC: can't create compress %s\n",
dai_link->stream_name);
- return ret;
- }
- } else if (!dai_link->params) {
+ return ret;
+ }
+
+ if (!dai_link->params) {
/* create the pcm */
ret = soc_new_pcm(rtd, num);
if (ret < 0) {
@@ -2394,26 +2395,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
/**
- * 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->driver->ops->set_sysclk)
- return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
-
- return snd_soc_component_set_sysclk(dai->component, clk_id, 0,
- freq, dir);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
-
-/**
* snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
* @component: COMPONENT
* @clk_id: DAI specific clock ID
@@ -2435,48 +2416,6 @@ int snd_soc_component_set_sysclk(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
-/**
- * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
- * @dai: DAI
- * @div_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->driver->ops->set_clkdiv)
- return dai->driver->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
- * @source: DAI specific source for the PLL
- * @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, int source,
- unsigned int freq_in, unsigned int freq_out)
-{
- if (dai->driver->ops->set_pll)
- return dai->driver->ops->set_pll(dai, pll_id, source,
- freq_in, freq_out);
-
- return snd_soc_component_set_pll(dai->component, pll_id, source,
- freq_in, freq_out);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
-
/*
* snd_soc_component_set_pll - configure component PLL.
* @component: COMPONENT
@@ -2499,187 +2438,6 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
-/**
- * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
- * @dai: DAI
- * @ratio: Ratio of BCLK to Sample rate.
- *
- * Configures the DAI for a preset BCLK to sample rate ratio.
- */
-int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
-{
- if (dai->driver->ops->set_bclk_ratio)
- return dai->driver->ops->set_bclk_ratio(dai, ratio);
- else
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
-
-/**
- * snd_soc_dai_set_fmt - configure DAI hardware audio format.
- * @dai: DAI
- * @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->driver->ops->set_fmt == NULL)
- return -ENOTSUPP;
- return dai->driver->ops->set_fmt(dai, fmt);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
-
-/**
- * snd_soc_xlate_tdm_slot - generate tx/rx slot mask.
- * @slots: Number of slots in use.
- * @tx_mask: bitmask representing active TX slots.
- * @rx_mask: bitmask representing active RX slots.
- *
- * Generates the TDM tx and rx slot default masks for DAI.
- */
-static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
- unsigned int *tx_mask,
- unsigned int *rx_mask)
-{
- if (*tx_mask || *rx_mask)
- return 0;
-
- if (!slots)
- return -EINVAL;
-
- *tx_mask = (1 << slots) - 1;
- *rx_mask = (1 << slots) - 1;
-
- return 0;
-}
-
-/**
- * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
- * @dai: The DAI to configure
- * @tx_mask: bitmask representing active TX slots.
- * @rx_mask: bitmask representing active RX slots.
- * @slots: Number of slots in use.
- * @slot_width: Width in bits for each slot.
- *
- * This function configures the specified DAI for TDM operation. @slot contains
- * the total number of slots of the TDM stream and @slot_with the width of each
- * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
- * active slots of the TDM stream for the specified DAI, i.e. which slots the
- * DAI should write to or read from. If a bit is set the corresponding slot is
- * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
- * the first slot, bit 1 to the second slot and so on. The first active slot
- * maps to the first channel of the DAI, the second active slot to the second
- * channel and so on.
- *
- * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
- * @rx_mask and @slot_width will be ignored.
- *
- * Returns 0 on success, a negative error code otherwise.
- */
-int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
-{
- if (dai->driver->ops->xlate_tdm_slot_mask)
- dai->driver->ops->xlate_tdm_slot_mask(slots,
- &tx_mask, &rx_mask);
- else
- snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
-
- dai->tx_mask = tx_mask;
- dai->rx_mask = rx_mask;
-
- if (dai->driver->ops->set_tdm_slot)
- return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
- slots, slot_width);
- else
- return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
-
-/**
- * snd_soc_dai_set_channel_map - configure DAI audio channel map
- * @dai: DAI
- * @tx_num: how many TX channels
- * @tx_slot: pointer to an array which imply the TX slot number channel
- * 0~num-1 uses
- * @rx_num: how many RX channels
- * @rx_slot: pointer to an array which imply the RX slot number channel
- * 0~num-1 uses
- *
- * configure the relationship between channel number and TDM slot number.
- */
-int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
- unsigned int tx_num, unsigned int *tx_slot,
- unsigned int rx_num, unsigned int *rx_slot)
-{
- if (dai->driver->ops->set_channel_map)
- return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
- rx_num, rx_slot);
- else
- return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
-
-/**
- * snd_soc_dai_get_channel_map - Get DAI audio channel map
- * @dai: DAI
- * @tx_num: how many TX channels
- * @tx_slot: pointer to an array which imply the TX slot number channel
- * 0~num-1 uses
- * @rx_num: how many RX channels
- * @rx_slot: pointer to an array which imply the RX slot number channel
- * 0~num-1 uses
- */
-int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
- unsigned int *tx_num, unsigned int *tx_slot,
- unsigned int *rx_num, unsigned int *rx_slot)
-{
- if (dai->driver->ops->get_channel_map)
- return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
- rx_num, rx_slot);
- else
- return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
-
-/**
- * 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->driver->ops->set_tristate)
- return dai->driver->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
- * @direction: stream to mute
- *
- * Mutes the DAI DAC.
- */
-int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
- int direction)
-{
- if (dai->driver->ops->mute_stream)
- return dai->driver->ops->mute_stream(dai, mute, direction);
- else if (direction == SNDRV_PCM_STREAM_PLAYBACK &&
- dai->driver->ops->digital_mute)
- return dai->driver->ops->digital_mute(dai, mute);
- else
- return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
-
static int snd_soc_bind_card(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
@@ -2748,14 +2506,12 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
snd_soc_dapm_shutdown(card);
snd_soc_flush_all_delayed_work(card);
- mutex_lock(&client_mutex);
/* remove all components used by DAI links on this card */
for_each_comp_order(order) {
for_each_card_rtds(card, rtd) {
soc_remove_link_components(card, rtd, order);
}
}
- mutex_unlock(&client_mutex);
soc_cleanup_card_resources(card);
if (!unregister)
@@ -2774,7 +2530,9 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
*/
int snd_soc_unregister_card(struct snd_soc_card *card)
{
+ mutex_lock(&client_mutex);
snd_soc_unbind_card(card, true);
+ mutex_unlock(&client_mutex);
dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
return 0;