Commit 10abe843 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/mxs' into asoc-next

parents 07797e9b 863ebdde
...@@ -169,6 +169,13 @@ struct snd_soc_dai_ops { ...@@ -169,6 +169,13 @@ struct snd_soc_dai_ops {
struct snd_soc_dai *); struct snd_soc_dai *);
int (*prepare)(struct snd_pcm_substream *, int (*prepare)(struct snd_pcm_substream *,
struct snd_soc_dai *); struct snd_soc_dai *);
/*
* NOTE: Commands passed to the trigger function are not necessarily
* compatible with the current state of the dai. For example this
* sequence of commands is possible: START STOP STOP.
* So do not unconditionally use refcounting functions in the trigger
* function, e.g. clk_enable/disable.
*/
int (*trigger)(struct snd_pcm_substream *, int, int (*trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *); struct snd_soc_dai *);
int (*bespoke_trigger)(struct snd_pcm_substream *, int, int (*bespoke_trigger)(struct snd_pcm_substream *, int,
......
...@@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
struct mxs_saif *master_saif; struct mxs_saif *master_saif;
u32 delay; u32 delay;
int ret;
master_saif = mxs_saif_get_master(saif); master_saif = mxs_saif_get_master(saif);
if (!master_saif) if (!master_saif)
...@@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (saif->state == MXS_SAIF_STATE_RUNNING)
return 0;
dev_dbg(cpu_dai->dev, "start\n"); dev_dbg(cpu_dai->dev, "start\n");
clk_enable(master_saif->clk); ret = clk_enable(master_saif->clk);
if (!master_saif->mclk_in_use) if (ret) {
__raw_writel(BM_SAIF_CTRL_RUN, dev_err(saif->dev, "Failed to enable master clock\n");
master_saif->base + SAIF_CTRL + MXS_SET_ADDR); return ret;
}
/* /*
* If the saif's master is not himself, we also need to enable * If the saif's master is not himself, we also need to enable
* itself clk for its internal basic logic to work. * itself clk for its internal basic logic to work.
*/ */
if (saif != master_saif) { if (saif != master_saif) {
clk_enable(saif->clk); ret = clk_enable(saif->clk);
if (ret) {
dev_err(saif->dev, "Failed to enable master clock\n");
clk_disable(master_saif->clk);
return ret;
}
__raw_writel(BM_SAIF_CTRL_RUN, __raw_writel(BM_SAIF_CTRL_RUN,
saif->base + SAIF_CTRL + MXS_SET_ADDR); saif->base + SAIF_CTRL + MXS_SET_ADDR);
} }
if (!master_saif->mclk_in_use)
__raw_writel(BM_SAIF_CTRL_RUN,
master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* /*
* write data to saif data register to trigger * write data to saif data register to trigger
...@@ -543,6 +558,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -543,6 +558,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
} }
master_saif->ongoing = 1; master_saif->ongoing = 1;
saif->state = MXS_SAIF_STATE_RUNNING;
dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
__raw_readl(saif->base + SAIF_CTRL), __raw_readl(saif->base + SAIF_CTRL),
...@@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (saif->state == MXS_SAIF_STATE_STOPPED)
return 0;
dev_dbg(cpu_dai->dev, "stop\n"); dev_dbg(cpu_dai->dev, "stop\n");
/* wait a while for the current sample to complete */ /* wait a while for the current sample to complete */
...@@ -575,6 +594,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -575,6 +594,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
} }
master_saif->ongoing = 0; master_saif->ongoing = 0;
saif->state = MXS_SAIF_STATE_STOPPED;
break; break;
default: default:
......
...@@ -124,6 +124,11 @@ struct mxs_saif { ...@@ -124,6 +124,11 @@ struct mxs_saif {
u32 fifo_underrun; u32 fifo_underrun;
u32 fifo_overrun; u32 fifo_overrun;
enum {
MXS_SAIF_STATE_STOPPED,
MXS_SAIF_STATE_RUNNING,
} state;
}; };
extern int mxs_saif_put_mclk(unsigned int saif_id); extern int mxs_saif_put_mclk(unsigned int saif_id);
......
...@@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = { ...@@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = {
.num_links = ARRAY_SIZE(mxs_sgtl5000_dai), .num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
}; };
static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) static int mxs_sgtl5000_probe(struct platform_device *pdev)
{ {
struct snd_soc_card *card = &mxs_sgtl5000;
int ret, i;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device_node *saif_np[2], *codec_np; struct device_node *saif_np[2], *codec_np;
int i;
if (!np)
return 1; /* no device tree */
saif_np[0] = of_parse_phandle(np, "saif-controllers", 0); saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
saif_np[1] = of_parse_phandle(np, "saif-controllers", 1); saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
...@@ -152,18 +150,6 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) ...@@ -152,18 +150,6 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
of_node_put(saif_np[0]); of_node_put(saif_np[0]);
of_node_put(saif_np[1]); of_node_put(saif_np[1]);
return 0;
}
static int mxs_sgtl5000_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mxs_sgtl5000;
int ret;
ret = mxs_sgtl5000_probe_dt(pdev);
if (ret < 0)
return ret;
/* /*
* Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
* The Sgtl5000 sysclk is derived from saif0 mclk and it's range * The Sgtl5000 sysclk is derived from saif0 mclk and it's range
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment