.. | .. |
---|
132 | 132 | |
---|
133 | 133 | /* Error Handling: TX */ |
---|
134 | 134 | if (isr[i] & ISR_TXFO) { |
---|
135 | | - dev_err(dev->dev, "TX overrun (ch_id=%d)\n", i); |
---|
| 135 | + dev_err_ratelimited(dev->dev, "TX overrun (ch_id=%d)\n", i); |
---|
136 | 136 | irq_valid = true; |
---|
137 | 137 | } |
---|
138 | 138 | |
---|
139 | 139 | /* Error Handling: TX */ |
---|
140 | 140 | if (isr[i] & ISR_RXFO) { |
---|
141 | | - dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i); |
---|
| 141 | + dev_err_ratelimited(dev->dev, "RX overrun (ch_id=%d)\n", i); |
---|
142 | 142 | irq_valid = true; |
---|
143 | 143 | } |
---|
144 | 144 | } |
---|
.. | .. |
---|
181 | 181 | i2s_write_reg(dev->i2s_base, CER, 0); |
---|
182 | 182 | i2s_write_reg(dev->i2s_base, IER, 0); |
---|
183 | 183 | } |
---|
184 | | -} |
---|
185 | | - |
---|
186 | | -static int dw_i2s_startup(struct snd_pcm_substream *substream, |
---|
187 | | - struct snd_soc_dai *cpu_dai) |
---|
188 | | -{ |
---|
189 | | - struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
---|
190 | | - union dw_i2s_snd_dma_data *dma_data = NULL; |
---|
191 | | - |
---|
192 | | - if (!(dev->capability & DWC_I2S_RECORD) && |
---|
193 | | - (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) |
---|
194 | | - return -EINVAL; |
---|
195 | | - |
---|
196 | | - if (!(dev->capability & DWC_I2S_PLAY) && |
---|
197 | | - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) |
---|
198 | | - return -EINVAL; |
---|
199 | | - |
---|
200 | | - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
---|
201 | | - dma_data = &dev->play_dma_data; |
---|
202 | | - else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
---|
203 | | - dma_data = &dev->capture_dma_data; |
---|
204 | | - |
---|
205 | | - snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); |
---|
206 | | - |
---|
207 | | - return 0; |
---|
208 | 184 | } |
---|
209 | 185 | |
---|
210 | 186 | static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) |
---|
.. | .. |
---|
305 | 281 | return 0; |
---|
306 | 282 | } |
---|
307 | 283 | |
---|
308 | | -static void dw_i2s_shutdown(struct snd_pcm_substream *substream, |
---|
309 | | - struct snd_soc_dai *dai) |
---|
310 | | -{ |
---|
311 | | - snd_soc_dai_set_dma_data(dai, substream, NULL); |
---|
312 | | -} |
---|
313 | | - |
---|
314 | 284 | static int dw_i2s_prepare(struct snd_pcm_substream *substream, |
---|
315 | 285 | struct snd_soc_dai *dai) |
---|
316 | 286 | { |
---|
.. | .. |
---|
382 | 352 | } |
---|
383 | 353 | |
---|
384 | 354 | static const struct snd_soc_dai_ops dw_i2s_dai_ops = { |
---|
385 | | - .startup = dw_i2s_startup, |
---|
386 | | - .shutdown = dw_i2s_shutdown, |
---|
387 | 355 | .hw_params = dw_i2s_hw_params, |
---|
388 | 356 | .prepare = dw_i2s_prepare, |
---|
389 | 357 | .trigger = dw_i2s_trigger, |
---|
390 | 358 | .set_fmt = dw_i2s_set_fmt, |
---|
391 | | -}; |
---|
392 | | - |
---|
393 | | -static const struct snd_soc_component_driver dw_i2s_component = { |
---|
394 | | - .name = "dw-i2s", |
---|
395 | 359 | }; |
---|
396 | 360 | |
---|
397 | 361 | #ifdef CONFIG_PM |
---|
.. | .. |
---|
407 | 371 | static int dw_i2s_runtime_resume(struct device *dev) |
---|
408 | 372 | { |
---|
409 | 373 | struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); |
---|
| 374 | + int ret; |
---|
410 | 375 | |
---|
411 | | - if (dw_dev->capability & DW_I2S_MASTER) |
---|
412 | | - clk_enable(dw_dev->clk); |
---|
| 376 | + if (dw_dev->capability & DW_I2S_MASTER) { |
---|
| 377 | + ret = clk_enable(dw_dev->clk); |
---|
| 378 | + if (ret) |
---|
| 379 | + return ret; |
---|
| 380 | + } |
---|
413 | 381 | return 0; |
---|
414 | 382 | } |
---|
415 | 383 | |
---|
416 | | -static int dw_i2s_suspend(struct snd_soc_dai *dai) |
---|
| 384 | +static int dw_i2s_suspend(struct snd_soc_component *component) |
---|
417 | 385 | { |
---|
418 | | - struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
---|
| 386 | + struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component); |
---|
419 | 387 | |
---|
420 | 388 | if (dev->capability & DW_I2S_MASTER) |
---|
421 | 389 | clk_disable(dev->clk); |
---|
422 | 390 | return 0; |
---|
423 | 391 | } |
---|
424 | 392 | |
---|
425 | | -static int dw_i2s_resume(struct snd_soc_dai *dai) |
---|
| 393 | +static int dw_i2s_resume(struct snd_soc_component *component) |
---|
426 | 394 | { |
---|
427 | | - struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
---|
| 395 | + struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component); |
---|
| 396 | + struct snd_soc_dai *dai; |
---|
| 397 | + int stream, ret; |
---|
428 | 398 | |
---|
429 | | - if (dev->capability & DW_I2S_MASTER) |
---|
430 | | - clk_enable(dev->clk); |
---|
| 399 | + if (dev->capability & DW_I2S_MASTER) { |
---|
| 400 | + ret = clk_enable(dev->clk); |
---|
| 401 | + if (ret) |
---|
| 402 | + return ret; |
---|
| 403 | + } |
---|
431 | 404 | |
---|
432 | | - if (dai->playback_active) |
---|
433 | | - dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK); |
---|
434 | | - if (dai->capture_active) |
---|
435 | | - dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); |
---|
| 405 | + for_each_component_dais(component, dai) { |
---|
| 406 | + for_each_pcm_streams(stream) |
---|
| 407 | + if (snd_soc_dai_stream_active(dai, stream)) |
---|
| 408 | + dw_i2s_config(dev, stream); |
---|
| 409 | + } |
---|
| 410 | + |
---|
436 | 411 | return 0; |
---|
437 | 412 | } |
---|
438 | 413 | |
---|
.. | .. |
---|
440 | 415 | #define dw_i2s_suspend NULL |
---|
441 | 416 | #define dw_i2s_resume NULL |
---|
442 | 417 | #endif |
---|
| 418 | + |
---|
| 419 | +static const struct snd_soc_component_driver dw_i2s_component = { |
---|
| 420 | + .name = "dw-i2s", |
---|
| 421 | + .suspend = dw_i2s_suspend, |
---|
| 422 | + .resume = dw_i2s_resume, |
---|
| 423 | +}; |
---|
443 | 424 | |
---|
444 | 425 | /* |
---|
445 | 426 | * The following tables allow a direct lookup of various parameters |
---|
.. | .. |
---|
611 | 592 | |
---|
612 | 593 | } |
---|
613 | 594 | |
---|
| 595 | +static int dw_i2s_dai_probe(struct snd_soc_dai *dai) |
---|
| 596 | +{ |
---|
| 597 | + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); |
---|
| 598 | + |
---|
| 599 | + snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data); |
---|
| 600 | + return 0; |
---|
| 601 | +} |
---|
| 602 | + |
---|
614 | 603 | static int dw_i2s_probe(struct platform_device *pdev) |
---|
615 | 604 | { |
---|
616 | 605 | const struct i2s_platform_data *pdata = pdev->dev.platform_data; |
---|
.. | .. |
---|
629 | 618 | return -ENOMEM; |
---|
630 | 619 | |
---|
631 | 620 | dw_i2s_dai->ops = &dw_i2s_dai_ops; |
---|
632 | | - dw_i2s_dai->suspend = dw_i2s_suspend; |
---|
633 | | - dw_i2s_dai->resume = dw_i2s_resume; |
---|
| 621 | + dw_i2s_dai->probe = dw_i2s_dai_probe; |
---|
634 | 622 | |
---|
635 | 623 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
636 | 624 | dev->i2s_base = devm_ioremap_resource(&pdev->dev, res); |
---|