diff options
| author | Rongjun Ying <rongjun.ying@csr.com> | 2014-07-23 01:19:32 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2014-07-25 13:54:44 -0400 |
| commit | 9779caf9faec1a366deb0b5877bfbc551917f03b (patch) | |
| tree | 2be96760ed428ed1e346b0ca0059982c4cac5a12 | |
| parent | 90eb1ab9e40c2d7596d9160151f6df4b5a71645f (diff) | |
ASoC: sirf-usp: Fixed a bug for playback and capture work at the same time
1. The startup function invoked when the playback and capture.
If start playback when capturing, the registers are re-initinitialised.
That cause the playback fail. So move the startup code into runtime resume.
2. Modified: If non RUNTIME_PM support, the probe need enable clock and
initinitialise registers.
3. Refine code.
Signed-off-by: Rongjun Ying <rongjun.ying@csr.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
| -rw-r--r-- | sound/soc/sirf/sirf-usp.c | 54 |
1 files changed, 27 insertions, 27 deletions
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 9693bc2a796d..3a730374e259 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c | |||
| @@ -103,11 +103,8 @@ static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai, | |||
| 103 | return 0; | 103 | return 0; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static int sirf_usp_i2s_startup(struct snd_pcm_substream *substream, | 106 | static void sirf_usp_i2s_init(struct sirf_usp *usp) |
| 107 | struct snd_soc_dai *dai) | ||
| 108 | { | 107 | { |
| 109 | struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); | ||
| 110 | |||
| 111 | /* Configure RISC mode */ | 108 | /* Configure RISC mode */ |
| 112 | regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE, | 109 | regmap_update_bits(usp->regmap, USP_RISC_DSP_MODE, |
| 113 | USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL); | 110 | USP_RISC_DSP_SEL, ~USP_RISC_DSP_SEL); |
| @@ -119,19 +116,16 @@ static int sirf_usp_i2s_startup(struct snd_pcm_substream *substream, | |||
| 119 | regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0); | 116 | regmap_write(usp->regmap, USP_TX_DMA_IO_LEN, 0); |
| 120 | regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0); | 117 | regmap_write(usp->regmap, USP_RX_DMA_IO_LEN, 0); |
| 121 | 118 | ||
| 122 | regmap_write(usp->regmap, USP_RX_FRAME_CTRL, USP_SINGLE_SYNC_MODE); | ||
| 123 | |||
| 124 | regmap_write(usp->regmap, USP_TX_FRAME_CTRL, USP_TXC_SLAVE_CLK_SAMPLE); | ||
| 125 | |||
| 126 | /* Configure Mode2 register */ | 119 | /* Configure Mode2 register */ |
| 127 | regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) | | 120 | regmap_write(usp->regmap, USP_MODE2, (1 << USP_RXD_DELAY_LEN_OFFSET) | |
| 128 | (0 << USP_TXD_DELAY_LEN_OFFSET)); | 121 | (0 << USP_TXD_DELAY_LEN_OFFSET) | |
| 122 | USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE); | ||
| 129 | 123 | ||
| 130 | /* Configure Mode1 register */ | 124 | /* Configure Mode1 register */ |
| 131 | regmap_write(usp->regmap, USP_MODE1, | 125 | regmap_write(usp->regmap, USP_MODE1, |
| 132 | USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING | | 126 | USP_SYNC_MODE | USP_EN | USP_TXD_ACT_EDGE_FALLING | |
| 133 | USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 | | 127 | USP_RFS_ACT_LEVEL_LOGIC1 | USP_TFS_ACT_LEVEL_LOGIC1 | |
| 134 | USP_TX_UFLOW_REPEAT_ZERO); | 128 | USP_TX_UFLOW_REPEAT_ZERO | USP_CLOCK_MODE_SLAVE); |
| 135 | 129 | ||
| 136 | /* Configure RX DMA IO Control register */ | 130 | /* Configure RX DMA IO Control register */ |
| 137 | regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0); | 131 | regmap_write(usp->regmap, USP_RX_DMA_IO_CTRL, 0); |
| @@ -155,8 +149,6 @@ static int sirf_usp_i2s_startup(struct snd_pcm_substream *substream, | |||
| 155 | /* Congiure TX FIFO Level Check register */ | 149 | /* Congiure TX FIFO Level Check register */ |
| 156 | regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK, | 150 | regmap_write(usp->regmap, USP_TX_FIFO_LEVEL_CHK, |
| 157 | TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04)); | 151 | TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04)); |
| 158 | |||
| 159 | return 0; | ||
| 160 | } | 152 | } |
| 161 | 153 | ||
| 162 | static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | 154 | static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, |
| @@ -204,23 +196,19 @@ static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 204 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 196 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 205 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, | 197 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, |
| 206 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK | 198 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK |
| 207 | | USP_TXC_SHIFTER_LEN_MASK, | 199 | | USP_TXC_SHIFTER_LEN_MASK | USP_TXC_SLAVE_CLK_SAMPLE, |
| 208 | ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET) | 200 | ((data_len - 1) << USP_TXC_DATA_LEN_OFFSET) |
| 209 | | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET) | 201 | | ((frame_len - 1) << USP_TXC_FRAME_LEN_OFFSET) |
| 210 | | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET)); | 202 | | ((shifter_len - 1) << USP_TXC_SHIFTER_LEN_OFFSET) |
| 203 | | USP_TXC_SLAVE_CLK_SAMPLE); | ||
| 211 | else | 204 | else |
| 212 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | 205 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, |
| 213 | USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK | 206 | USP_RXC_DATA_LEN_MASK | USP_RXC_FRAME_LEN_MASK |
| 214 | | USP_RXC_SHIFTER_LEN_MASK, | 207 | | USP_RXC_SHIFTER_LEN_MASK | USP_SINGLE_SYNC_MODE, |
| 215 | ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET) | 208 | ((data_len - 1) << USP_RXC_DATA_LEN_OFFSET) |
| 216 | | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET) | 209 | | ((frame_len - 1) << USP_RXC_FRAME_LEN_OFFSET) |
| 217 | | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET)); | 210 | | ((shifter_len - 1) << USP_RXC_SHIFTER_LEN_OFFSET) |
| 218 | 211 | | USP_SINGLE_SYNC_MODE); | |
| 219 | regmap_update_bits(usp->regmap, USP_MODE1, | ||
| 220 | USP_CLOCK_MODE_SLAVE, USP_CLOCK_MODE_SLAVE); | ||
| 221 | regmap_update_bits(usp->regmap, USP_MODE2, | ||
| 222 | USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE, | ||
| 223 | USP_TFS_CLK_SLAVE_MODE | USP_RFS_CLK_SLAVE_MODE); | ||
| 224 | 212 | ||
| 225 | return 0; | 213 | return 0; |
| 226 | } | 214 | } |
| @@ -253,7 +241,6 @@ static int sirf_usp_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 253 | } | 241 | } |
| 254 | 242 | ||
| 255 | static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = { | 243 | static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops = { |
| 256 | .startup = sirf_usp_i2s_startup, | ||
| 257 | .trigger = sirf_usp_pcm_trigger, | 244 | .trigger = sirf_usp_pcm_trigger, |
| 258 | .set_fmt = sirf_usp_pcm_set_dai_fmt, | 245 | .set_fmt = sirf_usp_pcm_set_dai_fmt, |
| 259 | .hw_params = sirf_usp_pcm_hw_params, | 246 | .hw_params = sirf_usp_pcm_hw_params, |
| @@ -282,7 +269,6 @@ static struct snd_soc_dai_driver sirf_usp_pcm_dai = { | |||
| 282 | .ops = &sirf_usp_pcm_dai_ops, | 269 | .ops = &sirf_usp_pcm_dai_ops, |
| 283 | }; | 270 | }; |
| 284 | 271 | ||
| 285 | #ifdef CONFIG_PM | ||
| 286 | static int sirf_usp_pcm_runtime_suspend(struct device *dev) | 272 | static int sirf_usp_pcm_runtime_suspend(struct device *dev) |
| 287 | { | 273 | { |
| 288 | struct sirf_usp *usp = dev_get_drvdata(dev); | 274 | struct sirf_usp *usp = dev_get_drvdata(dev); |
| @@ -293,9 +279,15 @@ static int sirf_usp_pcm_runtime_suspend(struct device *dev) | |||
| 293 | static int sirf_usp_pcm_runtime_resume(struct device *dev) | 279 | static int sirf_usp_pcm_runtime_resume(struct device *dev) |
| 294 | { | 280 | { |
| 295 | struct sirf_usp *usp = dev_get_drvdata(dev); | 281 | struct sirf_usp *usp = dev_get_drvdata(dev); |
| 296 | return clk_prepare_enable(usp->clk); | 282 | int ret; |
| 283 | ret = clk_prepare_enable(usp->clk); | ||
| 284 | if (ret) { | ||
| 285 | dev_err(dev, "clk_enable failed: %d\n", ret); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | sirf_usp_i2s_init(usp); | ||
| 289 | return 0; | ||
| 297 | } | 290 | } |
| 298 | #endif | ||
| 299 | 291 | ||
| 300 | #ifdef CONFIG_PM_SLEEP | 292 | #ifdef CONFIG_PM_SLEEP |
| 301 | static int sirf_usp_pcm_suspend(struct device *dev) | 293 | static int sirf_usp_pcm_suspend(struct device *dev) |
| @@ -369,6 +361,11 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) | |||
| 369 | } | 361 | } |
| 370 | 362 | ||
| 371 | pm_runtime_enable(&pdev->dev); | 363 | pm_runtime_enable(&pdev->dev); |
| 364 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
| 365 | ret = sirf_usp_pcm_runtime_resume(&pdev->dev); | ||
| 366 | if (ret) | ||
| 367 | return ret; | ||
| 368 | } | ||
| 372 | 369 | ||
| 373 | ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component, | 370 | ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component, |
| 374 | &sirf_usp_pcm_dai, 1); | 371 | &sirf_usp_pcm_dai, 1); |
| @@ -381,7 +378,10 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) | |||
| 381 | 378 | ||
| 382 | static int sirf_usp_pcm_remove(struct platform_device *pdev) | 379 | static int sirf_usp_pcm_remove(struct platform_device *pdev) |
| 383 | { | 380 | { |
| 384 | pm_runtime_disable(&pdev->dev); | 381 | if (!pm_runtime_enabled(&pdev->dev)) |
| 382 | sirf_usp_pcm_runtime_suspend(&pdev->dev); | ||
| 383 | else | ||
| 384 | pm_runtime_disable(&pdev->dev); | ||
| 385 | return 0; | 385 | return 0; |
| 386 | } | 386 | } |
| 387 | 387 | ||
