diff options
| -rw-r--r-- | include/sound/soc-dai.h | 7 | ||||
| -rw-r--r-- | sound/soc/mxs/mxs-saif.c | 30 | ||||
| -rw-r--r-- | sound/soc/mxs/mxs-saif.h | 5 | ||||
| -rw-r--r-- | sound/soc/mxs/mxs-sgtl5000.c | 20 |
4 files changed, 40 insertions, 22 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index b0ee6590b8ba..800c101bb096 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
| @@ -169,6 +169,13 @@ struct snd_soc_dai_ops { | |||
| 169 | struct snd_soc_dai *); | 169 | struct snd_soc_dai *); |
| 170 | int (*prepare)(struct snd_pcm_substream *, | 170 | int (*prepare)(struct snd_pcm_substream *, |
| 171 | struct snd_soc_dai *); | 171 | struct snd_soc_dai *); |
| 172 | /* | ||
| 173 | * NOTE: Commands passed to the trigger function are not necessarily | ||
| 174 | * compatible with the current state of the dai. For example this | ||
| 175 | * sequence of commands is possible: START STOP STOP. | ||
| 176 | * So do not unconditionally use refcounting functions in the trigger | ||
| 177 | * function, e.g. clk_enable/disable. | ||
| 178 | */ | ||
| 172 | int (*trigger)(struct snd_pcm_substream *, int, | 179 | int (*trigger)(struct snd_pcm_substream *, int, |
| 173 | struct snd_soc_dai *); | 180 | struct snd_soc_dai *); |
| 174 | int (*bespoke_trigger)(struct snd_pcm_substream *, int, | 181 | int (*bespoke_trigger)(struct snd_pcm_substream *, int, |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 14152f6f70dd..54e622acac33 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
| @@ -494,6 +494,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 494 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); | 494 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); |
| 495 | struct mxs_saif *master_saif; | 495 | struct mxs_saif *master_saif; |
| 496 | u32 delay; | 496 | u32 delay; |
| 497 | int ret; | ||
| 497 | 498 | ||
| 498 | master_saif = mxs_saif_get_master(saif); | 499 | master_saif = mxs_saif_get_master(saif); |
| 499 | if (!master_saif) | 500 | if (!master_saif) |
| @@ -503,23 +504,37 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 503 | case SNDRV_PCM_TRIGGER_START: | 504 | case SNDRV_PCM_TRIGGER_START: |
| 504 | case SNDRV_PCM_TRIGGER_RESUME: | 505 | case SNDRV_PCM_TRIGGER_RESUME: |
| 505 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 506 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 507 | if (saif->state == MXS_SAIF_STATE_RUNNING) | ||
| 508 | return 0; | ||
| 509 | |||
| 506 | dev_dbg(cpu_dai->dev, "start\n"); | 510 | dev_dbg(cpu_dai->dev, "start\n"); |
| 507 | 511 | ||
| 508 | clk_enable(master_saif->clk); | 512 | ret = clk_enable(master_saif->clk); |
| 509 | if (!master_saif->mclk_in_use) | 513 | if (ret) { |
| 510 | __raw_writel(BM_SAIF_CTRL_RUN, | 514 | dev_err(saif->dev, "Failed to enable master clock\n"); |
| 511 | master_saif->base + SAIF_CTRL + MXS_SET_ADDR); | 515 | return ret; |
| 516 | } | ||
| 512 | 517 | ||
| 513 | /* | 518 | /* |
| 514 | * If the saif's master is not himself, we also need to enable | 519 | * If the saif's master is not himself, we also need to enable |
| 515 | * itself clk for its internal basic logic to work. | 520 | * itself clk for its internal basic logic to work. |
| 516 | */ | 521 | */ |
| 517 | if (saif != master_saif) { | 522 | if (saif != master_saif) { |
| 518 | clk_enable(saif->clk); | 523 | ret = clk_enable(saif->clk); |
| 524 | if (ret) { | ||
| 525 | dev_err(saif->dev, "Failed to enable master clock\n"); | ||
| 526 | clk_disable(master_saif->clk); | ||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | |||
| 519 | __raw_writel(BM_SAIF_CTRL_RUN, | 530 | __raw_writel(BM_SAIF_CTRL_RUN, |
| 520 | saif->base + SAIF_CTRL + MXS_SET_ADDR); | 531 | saif->base + SAIF_CTRL + MXS_SET_ADDR); |
| 521 | } | 532 | } |
| 522 | 533 | ||
| 534 | if (!master_saif->mclk_in_use) | ||
| 535 | __raw_writel(BM_SAIF_CTRL_RUN, | ||
| 536 | master_saif->base + SAIF_CTRL + MXS_SET_ADDR); | ||
| 537 | |||
| 523 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 538 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 524 | /* | 539 | /* |
| 525 | * write data to saif data register to trigger | 540 | * 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 | } | 558 | } |
| 544 | 559 | ||
| 545 | master_saif->ongoing = 1; | 560 | master_saif->ongoing = 1; |
| 561 | saif->state = MXS_SAIF_STATE_RUNNING; | ||
| 546 | 562 | ||
| 547 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", | 563 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", |
| 548 | __raw_readl(saif->base + SAIF_CTRL), | 564 | __raw_readl(saif->base + SAIF_CTRL), |
| @@ -555,6 +571,9 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 555 | case SNDRV_PCM_TRIGGER_SUSPEND: | 571 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 556 | case SNDRV_PCM_TRIGGER_STOP: | 572 | case SNDRV_PCM_TRIGGER_STOP: |
| 557 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 573 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 574 | if (saif->state == MXS_SAIF_STATE_STOPPED) | ||
| 575 | return 0; | ||
| 576 | |||
| 558 | dev_dbg(cpu_dai->dev, "stop\n"); | 577 | dev_dbg(cpu_dai->dev, "stop\n"); |
| 559 | 578 | ||
| 560 | /* wait a while for the current sample to complete */ | 579 | /* 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 | } | 594 | } |
| 576 | 595 | ||
| 577 | master_saif->ongoing = 0; | 596 | master_saif->ongoing = 0; |
| 597 | saif->state = MXS_SAIF_STATE_STOPPED; | ||
| 578 | 598 | ||
| 579 | break; | 599 | break; |
| 580 | default: | 600 | default: |
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h index 53eaa4bf0e27..fbaf7badfdfb 100644 --- a/sound/soc/mxs/mxs-saif.h +++ b/sound/soc/mxs/mxs-saif.h | |||
| @@ -124,6 +124,11 @@ struct mxs_saif { | |||
| 124 | 124 | ||
| 125 | u32 fifo_underrun; | 125 | u32 fifo_underrun; |
| 126 | u32 fifo_overrun; | 126 | u32 fifo_overrun; |
| 127 | |||
| 128 | enum { | ||
| 129 | MXS_SAIF_STATE_STOPPED, | ||
| 130 | MXS_SAIF_STATE_RUNNING, | ||
| 131 | } state; | ||
| 127 | }; | 132 | }; |
| 128 | 133 | ||
| 129 | extern int mxs_saif_put_mclk(unsigned int saif_id); | 134 | extern int mxs_saif_put_mclk(unsigned int saif_id); |
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 4bb273786ff3..61822cc53bd3 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
| @@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = { | |||
| 122 | .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), | 122 | .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | static int mxs_sgtl5000_probe_dt(struct platform_device *pdev) | 125 | static int mxs_sgtl5000_probe(struct platform_device *pdev) |
| 126 | { | 126 | { |
| 127 | struct snd_soc_card *card = &mxs_sgtl5000; | ||
| 128 | int ret, i; | ||
| 127 | struct device_node *np = pdev->dev.of_node; | 129 | struct device_node *np = pdev->dev.of_node; |
| 128 | struct device_node *saif_np[2], *codec_np; | 130 | struct device_node *saif_np[2], *codec_np; |
| 129 | int i; | ||
| 130 | |||
| 131 | if (!np) | ||
| 132 | return 1; /* no device tree */ | ||
| 133 | 131 | ||
| 134 | saif_np[0] = of_parse_phandle(np, "saif-controllers", 0); | 132 | saif_np[0] = of_parse_phandle(np, "saif-controllers", 0); |
| 135 | saif_np[1] = of_parse_phandle(np, "saif-controllers", 1); | 133 | 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 | of_node_put(saif_np[0]); | 150 | of_node_put(saif_np[0]); |
| 153 | of_node_put(saif_np[1]); | 151 | of_node_put(saif_np[1]); |
| 154 | 152 | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int mxs_sgtl5000_probe(struct platform_device *pdev) | ||
| 159 | { | ||
| 160 | struct snd_soc_card *card = &mxs_sgtl5000; | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | ret = mxs_sgtl5000_probe_dt(pdev); | ||
| 164 | if (ret < 0) | ||
| 165 | return ret; | ||
| 166 | |||
| 167 | /* | 153 | /* |
| 168 | * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). | 154 | * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). |
| 169 | * The Sgtl5000 sysclk is derived from saif0 mclk and it's range | 155 | * The Sgtl5000 sysclk is derived from saif0 mclk and it's range |
