summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/amd/Kconfig2
-rw-r--r--sound/soc/atmel/mchp-i2s-mcc.c41
-rw-r--r--sound/soc/codecs/es8316.c7
-rw-r--r--sound/soc/codecs/rt1011.c27
-rw-r--r--sound/soc/fsl/fsl_ssi.c18
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-pcm.c1
-rw-r--r--sound/soc/intel/common/sst-ipc.c2
-rw-r--r--sound/soc/intel/skylake/skl-debug.c2
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.c2
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c3
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c6
-rw-r--r--sound/soc/soc-topology.c6
-rw-r--r--sound/soc/ti/ams-delta.c31
-rw-r--r--sound/soc/ti/davinci-i2s.c82
14 files changed, 136 insertions, 94 deletions
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 9ca9214cb7fb..5f40517717c4 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -10,7 +10,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
select REGULATOR
- depends on SND_SOC_AMD_ACP && I2C
+ depends on SND_SOC_AMD_ACP && I2C && GPIOLIB
help
This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 9a406144b18f..befc2a3a05b0 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -674,8 +674,13 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
dev->channels = channels;
ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra);
- if (ret < 0)
+ if (ret < 0) {
+ if (dev->gclk_use) {
+ clk_unprepare(dev->gclk);
+ dev->gclk_use = 0;
+ }
return ret;
+ }
return regmap_write(dev->regmap, MCHP_I2SMCC_MRB, mrb);
}
@@ -690,31 +695,37 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream,
err = wait_event_interruptible_timeout(dev->wq_txrdy,
dev->tx_rdy,
msecs_to_jiffies(500));
+ if (err == 0) {
+ dev_warn_once(dev->dev,
+ "Timeout waiting for Tx ready\n");
+ regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+ MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+ dev->tx_rdy = 1;
+ }
} else {
err = wait_event_interruptible_timeout(dev->wq_rxrdy,
dev->rx_rdy,
msecs_to_jiffies(500));
- }
-
- if (err == 0) {
- u32 idra;
-
- dev_warn_once(dev->dev, "Timeout waiting for %s\n",
- is_playback ? "Tx ready" : "Rx ready");
- if (is_playback)
- idra = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels);
- else
- idra = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels);
- regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
+ if (err == 0) {
+ dev_warn_once(dev->dev,
+ "Timeout waiting for Rx ready\n");
+ regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
+ MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+ dev->rx_rdy = 1;
+ }
}
if (!mchp_i2s_mcc_is_running(dev)) {
regmap_write(dev->regmap, MCHP_I2SMCC_CR, MCHP_I2SMCC_CR_CKDIS);
if (dev->gclk_running) {
- clk_disable_unprepare(dev->gclk);
+ clk_disable(dev->gclk);
dev->gclk_running = 0;
}
+ if (dev->gclk_use) {
+ clk_unprepare(dev->gclk);
+ dev->gclk_use = 0;
+ }
}
return 0;
@@ -813,6 +824,8 @@ static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai)
init_waitqueue_head(&dev->wq_txrdy);
init_waitqueue_head(&dev->wq_rxrdy);
+ dev->tx_rdy = 1;
+ dev->rx_rdy = 1;
snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 9150e7068467..36eef1fb3d18 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -53,7 +53,10 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
-static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
+ 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
+ 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
+);
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
@@ -91,7 +94,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = {
SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
4, 0, 3, 1, hpout_vol_tlv),
SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
- 0, 4, 7, 0, hpmixer_gain_tlv),
+ 4, 0, 11, 0, hpmixer_gain_tlv),
SOC_ENUM("Playback Polarity", dacpol),
SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c
index a92a0bacd812..be1e276e3631 100644
--- a/sound/soc/codecs/rt1011.c
+++ b/sound/soc/codecs/rt1011.c
@@ -1628,14 +1628,18 @@ static int rt1011_hw_params(struct snd_pcm_substream *substream,
static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
unsigned int reg_val = 0, reg_bclk_inv = 0;
+ int ret = 0;
+ snd_soc_dapm_mutex_lock(dapm);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
reg_val |= RT1011_I2S_TDM_MS_S;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -1645,7 +1649,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
reg_bclk_inv |= RT1011_TDM_INV_BCLK;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1661,7 +1665,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
reg_val |= RT1011_I2S_TDM_DF_PCM_B;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
switch (dai->id) {
@@ -1676,9 +1680,11 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
break;
default:
dev_err(component->dev, "Invalid dai->id: %d\n", dai->id);
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+
+ snd_soc_dapm_mutex_unlock(dapm);
+ return ret;
}
static int rt1011_set_component_sysclk(struct snd_soc_component *component,
@@ -1797,8 +1803,12 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
unsigned int val = 0, tdm_en = 0;
+ int ret = 0;
+ snd_soc_dapm_mutex_lock(dapm);
if (rx_mask || tx_mask)
tdm_en = RT1011_TDM_I2S_DOCK_EN_1;
@@ -1818,7 +1828,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
case 2:
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
switch (slot_width) {
@@ -1837,7 +1847,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
case 16:
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
@@ -1854,7 +1864,8 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
- return 0;
+ snd_soc_dapm_mutex_unlock(dapm);
+ return ret;
}
static int rt1011_probe(struct snd_soc_component *component)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b0a6fead1a6a..537dc69256f0 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -799,15 +799,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
- /*
- * SSI is properly configured if it is enabled and running in
- * the synchronous mode; Note that AC97 mode is an exception
- * that should set separate configurations for STCCR and SRCCR
- * despite running in the synchronous mode.
- */
- if (ssi->streams && ssi->synchronous)
- return 0;
-
if (fsl_ssi_is_i2s_master(ssi)) {
ret = fsl_ssi_set_bclk(substream, dai, hw_params);
if (ret)
@@ -823,6 +814,15 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
}
}
+ /*
+ * SSI is properly configured if it is enabled and running in
+ * the synchronous mode; Note that AC97 mode is an exception
+ * that should set separate configurations for STCCR and SRCCR
+ * despite running in the synchronous mode.
+ */
+ if (ssi->streams && ssi->synchronous)
+ return 0;
+
if (!fsl_ssi_is_ac97(ssi)) {
/*
* Keep the ssi->i2s_net intact while having a local variable
diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
index 9cbc982d46a9..54f2ee3010ee 100644
--- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
@@ -193,6 +193,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
pdata->restore_stream = false;
+ /* fallthrough */
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
sst_byt_stream_pause(byt, pcm_data->stream);
break;
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
index 1186a03a88d6..6068bb697e22 100644
--- a/sound/soc/intel/common/sst-ipc.c
+++ b/sound/soc/intel/common/sst-ipc.c
@@ -223,6 +223,8 @@ struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
if (ipc->ops.reply_msg_match != NULL)
header = ipc->ops.reply_msg_match(header, &mask);
+ else
+ mask = (u64)-1;
if (list_empty(&ipc->rx_list)) {
dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c
index 212370bf704c..3466675f2678 100644
--- a/sound/soc/intel/skylake/skl-debug.c
+++ b/sound/soc/intel/skylake/skl-debug.c
@@ -188,7 +188,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
memset(d->fw_read_buff, 0, FW_REG_BUF);
if (w0_stat_sz > 0)
- __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
+ __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index ab3d23c7bd65..19f328d71f24 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -136,7 +136,7 @@ int skl_nhlt_update_topology_bin(struct skl_dev *skl)
struct hdac_bus *bus = skl_to_bus(skl);
struct device *dev = bus->dev;
- dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n",
+ dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n",
nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision);
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index d16563408465..10ea4fdbeb1e 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -241,7 +241,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
int hd_audio = 0;
- int hd_align = 1;
+ int hd_align = 0;
/* set hd mode */
switch (substream->runtime->format) {
@@ -254,7 +254,6 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
break;
case SNDRV_PCM_FORMAT_S24_LE:
hd_audio = 1;
- hd_align = 0;
break;
default:
dev_err(afe->dev, "%s() error: unsupported format %d\n",
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 748f5f641002..5552c66ca642 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -306,6 +306,12 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i]))
pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE;
+
+ if (rtd->pcm->streams[i].pcm->name[0] == '\0') {
+ strscpy_pad(rtd->pcm->streams[i].pcm->name,
+ rtd->pcm->streams[i].pcm->id,
+ sizeof(rtd->pcm->streams[i].pcm->name));
+ }
}
return 0;
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index b8690715abb5..aa9a1fca46fa 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -80,12 +80,6 @@ struct soc_tplg {
static int soc_tplg_process_headers(struct soc_tplg *tplg);
static void soc_tplg_complete(struct soc_tplg *tplg);
-struct snd_soc_dapm_widget *
-snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget);
-struct snd_soc_dapm_widget *
-snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget);
static void soc_tplg_denum_remove_texts(struct soc_enum *se);
static void soc_tplg_denum_remove_values(struct soc_enum *se);
diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c
index dee8fc70a64f..8e2fb81ad05c 100644
--- a/sound/soc/ti/ams-delta.c
+++ b/sound/soc/ti/ams-delta.c
@@ -23,14 +23,31 @@
#include "omap-mcbsp.h"
#include "../codecs/cx20442.h"
+static struct gpio_desc *handset_mute;
+static struct gpio_desc *handsfree_mute;
+
+static int ams_delta_event_handset(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ gpiod_set_value_cansleep(handset_mute, !SND_SOC_DAPM_EVENT_ON(event));
+ return 0;
+}
+
+static int ams_delta_event_handsfree(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ gpiod_set_value_cansleep(handsfree_mute, !SND_SOC_DAPM_EVENT_ON(event));
+ return 0;
+}
+
/* Board specific DAPM widgets */
static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
/* Handset */
SND_SOC_DAPM_MIC("Mouthpiece", NULL),
- SND_SOC_DAPM_HP("Earpiece", NULL),
+ SND_SOC_DAPM_HP("Earpiece", ams_delta_event_handset),
/* Handsfree/Speakerphone */
SND_SOC_DAPM_MIC("Microphone", NULL),
- SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_SPK("Speaker", ams_delta_event_handsfree),
};
/* How they are connected to codec pins */
@@ -542,6 +559,16 @@ static int ams_delta_probe(struct platform_device *pdev)
card->dev = &pdev->dev;
+ handset_mute = devm_gpiod_get(card->dev, "handset_mute",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(handset_mute))
+ return PTR_ERR(handset_mute);
+
+ handsfree_mute = devm_gpiod_get(card->dev, "handsfree_mute",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(handsfree_mute))
+ return PTR_ERR(handsfree_mute);
+
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c
index f04d9fb5130f..d89b5c928c4d 100644
--- a/sound/soc/ti/davinci-i2s.c
+++ b/sound/soc/ti/davinci-i2s.c
@@ -187,57 +187,9 @@ static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
u32 spcr;
u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
- spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- if (spcr & mask) {
- /* start off disabled */
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
- spcr & ~mask);
- toggle_clock(dev, playback);
- }
- if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
- DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
- /* Start the sample generator */
- spcr |= DAVINCI_MCBSP_SPCR_GRST;
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
- }
-
- if (playback) {
- /* Stop the DMA to avoid data loss */
- /* while the transmitter is out of reset to handle XSYNCERR */
- if (component->driver->ops->trigger) {
- int ret = component->driver->ops->trigger(substream,
- SNDRV_PCM_TRIGGER_STOP);
- if (ret < 0)
- printk(KERN_DEBUG "Playback DMA stop failed\n");
- }
-
- /* Enable the transmitter */
- spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- spcr |= DAVINCI_MCBSP_SPCR_XRST;
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
-
- /* wait for any unexpected frame sync error to occur */
- udelay(100);
-
- /* Disable the transmitter to clear any outstanding XSYNCERR */
- spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
- toggle_clock(dev, playback);
-
- /* Restart the DMA */
- if (component->driver->ops->trigger) {
- int ret = component->driver->ops->trigger(substream,
- SNDRV_PCM_TRIGGER_START);
- if (ret < 0)
- printk(KERN_DEBUG "Playback DMA start failed\n");
- }
- }
/* Enable transmitter or receiver */
spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -575,7 +527,41 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
{
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+ u32 spcr;
+ u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
+
davinci_mcbsp_stop(dev, playback);
+
+ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ if (spcr & mask) {
+ /* start off disabled */
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
+ spcr & ~mask);
+ toggle_clock(dev, playback);
+ }
+ if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
+ DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
+ /* Start the sample generator */
+ spcr |= DAVINCI_MCBSP_SPCR_GRST;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+ }
+
+ if (playback) {
+ /* Enable the transmitter */
+ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ spcr |= DAVINCI_MCBSP_SPCR_XRST;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+
+ /* wait for any unexpected frame sync error to occur */
+ udelay(100);
+
+ /* Disable the transmitter to clear any outstanding XSYNCERR */
+ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+ toggle_clock(dev, playback);
+ }
+
return 0;
}