diff options
Diffstat (limited to 'sound/soc/tegra/tegra30_i2s.c')
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 47565fd04505..5f20b695eba2 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/of.h> | 32 | #include <linux/of.h> |
33 | #include <linux/of_device.h> | ||
33 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
34 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
35 | #include <linux/regmap.h> | 36 | #include <linux/regmap.h> |
@@ -179,6 +180,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
179 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 180 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
180 | unsigned int mask, val, reg; | 181 | unsigned int mask, val, reg; |
181 | int ret, sample_size, srate, i2sclock, bitcnt; | 182 | int ret, sample_size, srate, i2sclock, bitcnt; |
183 | struct tegra30_ahub_cif_conf cif_conf; | ||
182 | 184 | ||
183 | if (params_channels(params) != 2) | 185 | if (params_channels(params) != 2) |
184 | return -EINVAL; | 186 | return -EINVAL; |
@@ -217,21 +219,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
217 | 219 | ||
218 | regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); | 220 | regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); |
219 | 221 | ||
220 | val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | | 222 | cif_conf.threshold = 0; |
221 | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | | 223 | cif_conf.audio_channels = 2; |
222 | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | | 224 | cif_conf.client_channels = 2; |
223 | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | | 225 | cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; |
224 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16; | 226 | cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; |
227 | cif_conf.expand = 0; | ||
228 | cif_conf.stereo_conv = 0; | ||
229 | cif_conf.replicate = 0; | ||
230 | cif_conf.truncate = 0; | ||
231 | cif_conf.mono_conv = 0; | ||
225 | 232 | ||
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 233 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
227 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; | 234 | cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; |
228 | reg = TEGRA30_I2S_CIF_RX_CTRL; | 235 | reg = TEGRA30_I2S_CIF_RX_CTRL; |
229 | } else { | 236 | } else { |
230 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; | 237 | cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; |
231 | reg = TEGRA30_I2S_CIF_TX_CTRL; | 238 | reg = TEGRA30_I2S_CIF_TX_CTRL; |
232 | } | 239 | } |
233 | 240 | ||
234 | regmap_write(i2s->regmap, reg, val); | 241 | i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf); |
235 | 242 | ||
236 | val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | | 243 | val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | |
237 | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); | 244 | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); |
@@ -396,9 +403,24 @@ static const struct regmap_config tegra30_i2s_regmap_config = { | |||
396 | .cache_type = REGCACHE_RBTREE, | 403 | .cache_type = REGCACHE_RBTREE, |
397 | }; | 404 | }; |
398 | 405 | ||
406 | static const struct tegra30_i2s_soc_data tegra30_i2s_config = { | ||
407 | .set_audio_cif = tegra30_ahub_set_cif, | ||
408 | }; | ||
409 | |||
410 | static const struct tegra30_i2s_soc_data tegra124_i2s_config = { | ||
411 | .set_audio_cif = tegra124_ahub_set_cif, | ||
412 | }; | ||
413 | |||
414 | static const struct of_device_id tegra30_i2s_of_match[] = { | ||
415 | { .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config }, | ||
416 | { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config }, | ||
417 | {}, | ||
418 | }; | ||
419 | |||
399 | static int tegra30_i2s_platform_probe(struct platform_device *pdev) | 420 | static int tegra30_i2s_platform_probe(struct platform_device *pdev) |
400 | { | 421 | { |
401 | struct tegra30_i2s *i2s; | 422 | struct tegra30_i2s *i2s; |
423 | const struct of_device_id *match; | ||
402 | u32 cif_ids[2]; | 424 | u32 cif_ids[2]; |
403 | struct resource *mem, *memregion; | 425 | struct resource *mem, *memregion; |
404 | void __iomem *regs; | 426 | void __iomem *regs; |
@@ -412,6 +434,14 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) | |||
412 | } | 434 | } |
413 | dev_set_drvdata(&pdev->dev, i2s); | 435 | dev_set_drvdata(&pdev->dev, i2s); |
414 | 436 | ||
437 | match = of_match_device(tegra30_i2s_of_match, &pdev->dev); | ||
438 | if (!match) { | ||
439 | dev_err(&pdev->dev, "Error: No device match found\n"); | ||
440 | ret = -ENODEV; | ||
441 | goto err; | ||
442 | } | ||
443 | i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data; | ||
444 | |||
415 | i2s->dai = tegra30_i2s_dai_template; | 445 | i2s->dai = tegra30_i2s_dai_template; |
416 | i2s->dai.name = dev_name(&pdev->dev); | 446 | i2s->dai.name = dev_name(&pdev->dev); |
417 | 447 | ||
@@ -539,11 +569,6 @@ static int tegra30_i2s_resume(struct device *dev) | |||
539 | } | 569 | } |
540 | #endif | 570 | #endif |
541 | 571 | ||
542 | static const struct of_device_id tegra30_i2s_of_match[] = { | ||
543 | { .compatible = "nvidia,tegra30-i2s", }, | ||
544 | {}, | ||
545 | }; | ||
546 | |||
547 | static const struct dev_pm_ops tegra30_i2s_pm_ops = { | 572 | static const struct dev_pm_ops tegra30_i2s_pm_ops = { |
548 | SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, | 573 | SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, |
549 | tegra30_i2s_runtime_resume, NULL) | 574 | tegra30_i2s_runtime_resume, NULL) |