aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-10-11 17:43:17 -0400
committerMark Brown <broonie@linaro.org>2013-10-14 09:56:27 -0400
commit5e049fce368dfe07702c3664add9ae7b45df1a9a (patch)
treea3e361dd4f1183b4977129cf571d34ea229245ce /sound/soc/tegra
parent61e6cfa80de5760bbe406f4e815b7739205754d2 (diff)
ASoC: tegra: support new register layouts in Tegra124
Tegra124 introduces some small changes to the layout of some registers. Modify the affected drivers to program those registers appropriately based on which SoC they're running on. Tegra124 also introduced some new modules on the AHUB configlink register bus. These will require new entries in configlink_clocks[] in the AHUB driver. However, supporting that change likely relies on switching Tegra to the common reset framework, so I'll defer that change for now. Based-on-work-by: Arun Shamanna Lakshmi <aruns@nvidia.com> Based-on-work-by: Songhee Baek <sbaek@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/tegra30_ahub.c115
-rw-r--r--sound/soc/tegra/tegra30_ahub.h38
-rw-r--r--sound/soc/tegra/tegra30_i2s.c51
-rw-r--r--sound/soc/tegra/tegra30_i2s.h7
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c2
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h1
6 files changed, 186 insertions, 28 deletions
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index d554d46d08b5..bdd19db4a08b 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -100,6 +100,7 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
100{ 100{
101 int channel; 101 int channel;
102 u32 reg, val; 102 u32 reg, val;
103 struct tegra30_ahub_cif_conf cif_conf;
103 104
104 channel = find_first_zero_bit(ahub->rx_usage, 105 channel = find_first_zero_bit(ahub->rx_usage,
105 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 106 TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
@@ -123,15 +124,21 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif,
123 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16; 124 TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
124 tegra30_apbif_write(reg, val); 125 tegra30_apbif_write(reg, val);
125 126
127 cif_conf.threshold = 0;
128 cif_conf.audio_channels = 2;
129 cif_conf.client_channels = 2;
130 cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
131 cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
132 cif_conf.expand = 0;
133 cif_conf.stereo_conv = 0;
134 cif_conf.replicate = 0;
135 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
136 cif_conf.truncate = 0;
137 cif_conf.mono_conv = 0;
138
126 reg = TEGRA30_AHUB_CIF_RX_CTRL + 139 reg = TEGRA30_AHUB_CIF_RX_CTRL +
127 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); 140 (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
128 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 141 ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
129 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
130 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
131 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
132 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
133 TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
134 tegra30_apbif_write(reg, val);
135 142
136 return 0; 143 return 0;
137} 144}
@@ -183,6 +190,7 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
183{ 190{
184 int channel; 191 int channel;
185 u32 reg, val; 192 u32 reg, val;
193 struct tegra30_ahub_cif_conf cif_conf;
186 194
187 channel = find_first_zero_bit(ahub->tx_usage, 195 channel = find_first_zero_bit(ahub->tx_usage,
188 TEGRA30_AHUB_CHANNEL_CTRL_COUNT); 196 TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
@@ -206,15 +214,21 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif,
206 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16; 214 TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
207 tegra30_apbif_write(reg, val); 215 tegra30_apbif_write(reg, val);
208 216
217 cif_conf.threshold = 0;
218 cif_conf.audio_channels = 2;
219 cif_conf.client_channels = 2;
220 cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
221 cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
222 cif_conf.expand = 0;
223 cif_conf.stereo_conv = 0;
224 cif_conf.replicate = 0;
225 cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
226 cif_conf.truncate = 0;
227 cif_conf.mono_conv = 0;
228
209 reg = TEGRA30_AHUB_CIF_TX_CTRL + 229 reg = TEGRA30_AHUB_CIF_TX_CTRL +
210 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); 230 (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
211 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 231 ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
212 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
213 (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
214 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
215 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
216 TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
217 tegra30_apbif_write(reg, val);
218 232
219 return 0; 233 return 0;
220} 234}
@@ -437,13 +451,21 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
437 451
438static struct tegra30_ahub_soc_data soc_data_tegra30 = { 452static struct tegra30_ahub_soc_data soc_data_tegra30 = {
439 .clk_list_mask = CLK_LIST_MASK_TEGRA30, 453 .clk_list_mask = CLK_LIST_MASK_TEGRA30,
454 .set_audio_cif = tegra30_ahub_set_cif,
440}; 455};
441 456
442static struct tegra30_ahub_soc_data soc_data_tegra114 = { 457static struct tegra30_ahub_soc_data soc_data_tegra114 = {
443 .clk_list_mask = CLK_LIST_MASK_TEGRA114, 458 .clk_list_mask = CLK_LIST_MASK_TEGRA114,
459 .set_audio_cif = tegra30_ahub_set_cif,
460};
461
462static struct tegra30_ahub_soc_data soc_data_tegra124 = {
463 .clk_list_mask = CLK_LIST_MASK_TEGRA114,
464 .set_audio_cif = tegra124_ahub_set_cif,
444}; 465};
445 466
446static const struct of_device_id tegra30_ahub_of_match[] = { 467static const struct of_device_id tegra30_ahub_of_match[] = {
468 { .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 },
447 { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 }, 469 { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
448 { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, 470 { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 },
449 {}, 471 {},
@@ -497,6 +519,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
497 } 519 }
498 dev_set_drvdata(&pdev->dev, ahub); 520 dev_set_drvdata(&pdev->dev, ahub);
499 521
522 ahub->soc_data = soc_data;
500 ahub->dev = &pdev->dev; 523 ahub->dev = &pdev->dev;
501 524
502 ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); 525 ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
@@ -669,6 +692,70 @@ static struct platform_driver tegra30_ahub_driver = {
669}; 692};
670module_platform_driver(tegra30_ahub_driver); 693module_platform_driver(tegra30_ahub_driver);
671 694
695void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
696 struct tegra30_ahub_cif_conf *conf)
697{
698 unsigned int value;
699
700 value = (conf->threshold <<
701 TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
702 ((conf->audio_channels - 1) <<
703 TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
704 ((conf->client_channels - 1) <<
705 TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
706 (conf->audio_bits <<
707 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
708 (conf->client_bits <<
709 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
710 (conf->expand <<
711 TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
712 (conf->stereo_conv <<
713 TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
714 (conf->replicate <<
715 TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
716 (conf->direction <<
717 TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
718 (conf->truncate <<
719 TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
720 (conf->mono_conv <<
721 TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
722
723 regmap_write(regmap, reg, value);
724}
725EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif);
726
727void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
728 struct tegra30_ahub_cif_conf *conf)
729{
730 unsigned int value;
731
732 value = (conf->threshold <<
733 TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
734 ((conf->audio_channels - 1) <<
735 TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
736 ((conf->client_channels - 1) <<
737 TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
738 (conf->audio_bits <<
739 TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
740 (conf->client_bits <<
741 TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
742 (conf->expand <<
743 TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
744 (conf->stereo_conv <<
745 TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
746 (conf->replicate <<
747 TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
748 (conf->direction <<
749 TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
750 (conf->truncate <<
751 TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
752 (conf->mono_conv <<
753 TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
754
755 regmap_write(regmap, reg, value);
756}
757EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif);
758
672MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 759MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
673MODULE_DESCRIPTION("Tegra30 AHUB driver"); 760MODULE_DESCRIPTION("Tegra30 AHUB driver");
674MODULE_LICENSE("GPL v2"); 761MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 09766cdc45ca..d67321d90faa 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -25,16 +25,30 @@
25#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf 25#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf
26#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) 26#define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
27 27
28#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 24
29#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0x3f
30#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
31
28/* Channel count minus 1 */ 32/* Channel count minus 1 */
29#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24 33#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24
30#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7 34#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7
31#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) 35#define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
32 36
33/* Channel count minus 1 */ 37/* Channel count minus 1 */
38#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 20
39#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 0xf
40#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
41
42/* Channel count minus 1 */
34#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16 43#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
35#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7 44#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7
36#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) 45#define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
37 46
47/* Channel count minus 1 */
48#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16
49#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 0xf
50#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
51
38#define TEGRA30_AUDIOCIF_BITS_4 0 52#define TEGRA30_AUDIOCIF_BITS_4 0
39#define TEGRA30_AUDIOCIF_BITS_8 1 53#define TEGRA30_AUDIOCIF_BITS_8 1
40#define TEGRA30_AUDIOCIF_BITS_12 2 54#define TEGRA30_AUDIOCIF_BITS_12 2
@@ -86,7 +100,7 @@
86#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) 100#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
87#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) 101#define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
88 102
89#define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3 103#define TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT 3
90 104
91#define TEGRA30_AUDIOCIF_DIRECTION_TX 0 105#define TEGRA30_AUDIOCIF_DIRECTION_TX 0
92#define TEGRA30_AUDIOCIF_DIRECTION_RX 1 106#define TEGRA30_AUDIOCIF_DIRECTION_RX 1
@@ -468,8 +482,30 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif,
468 enum tegra30_ahub_txcif txcif); 482 enum tegra30_ahub_txcif txcif);
469extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif); 483extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
470 484
485struct tegra30_ahub_cif_conf {
486 unsigned int threshold;
487 unsigned int audio_channels;
488 unsigned int client_channels;
489 unsigned int audio_bits;
490 unsigned int client_bits;
491 unsigned int expand;
492 unsigned int stereo_conv;
493 unsigned int replicate;
494 unsigned int direction;
495 unsigned int truncate;
496 unsigned int mono_conv;
497};
498
499void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
500 struct tegra30_ahub_cif_conf *conf);
501void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
502 struct tegra30_ahub_cif_conf *conf);
503
471struct tegra30_ahub_soc_data { 504struct tegra30_ahub_soc_data {
472 u32 clk_list_mask; 505 u32 clk_list_mask;
506 void (*set_audio_cif)(struct regmap *regmap,
507 unsigned int reg,
508 struct tegra30_ahub_cif_conf *conf);
473 /* 509 /*
474 * FIXME: There are many more differences in HW, such as: 510 * FIXME: There are many more differences in HW, such as:
475 * - More APBIF channels. 511 * - More APBIF channels.
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
406static const struct tegra30_i2s_soc_data tegra30_i2s_config = {
407 .set_audio_cif = tegra30_ahub_set_cif,
408};
409
410static const struct tegra30_i2s_soc_data tegra124_i2s_config = {
411 .set_audio_cif = tegra124_ahub_set_cif,
412};
413
414static 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
399static int tegra30_i2s_platform_probe(struct platform_device *pdev) 420static 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
542static const struct of_device_id tegra30_i2s_of_match[] = {
543 { .compatible = "nvidia,tegra30-i2s", },
544 {},
545};
546
547static const struct dev_pm_ops tegra30_i2s_pm_ops = { 572static 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)
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index bea23afe3b9f..4d0b0a30dbfb 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -225,7 +225,14 @@
225#define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff 225#define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff
226#define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT) 226#define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT)
227 227
228struct tegra30_i2s_soc_data {
229 void (*set_audio_cif)(struct regmap *regmap,
230 unsigned int reg,
231 struct tegra30_ahub_cif_conf *conf);
232};
233
228struct tegra30_i2s { 234struct tegra30_i2s {
235 const struct tegra30_i2s_soc_data *soc_data;
229 struct snd_soc_dai_driver dai; 236 struct snd_soc_dai_driver dai;
230 int cif_id; 237 int cif_id;
231 struct clk *clk_i2s; 238 struct clk *clk_i2s;
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index d173880f290d..1be311c51a18 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -182,6 +182,8 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
182 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; 182 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
183 else if (of_machine_is_compatible("nvidia,tegra114")) 183 else if (of_machine_is_compatible("nvidia,tegra114"))
184 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; 184 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
185 else if (of_machine_is_compatible("nvidia,tegra124"))
186 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124;
185 else { 187 else {
186 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); 188 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
187 return -EINVAL; 189 return -EINVAL;
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 19fdcafed32f..9577121ce971 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -30,6 +30,7 @@ enum tegra_asoc_utils_soc {
30 TEGRA_ASOC_UTILS_SOC_TEGRA20, 30 TEGRA_ASOC_UTILS_SOC_TEGRA20,
31 TEGRA_ASOC_UTILS_SOC_TEGRA30, 31 TEGRA_ASOC_UTILS_SOC_TEGRA30,
32 TEGRA_ASOC_UTILS_SOC_TEGRA114, 32 TEGRA_ASOC_UTILS_SOC_TEGRA114,
33 TEGRA_ASOC_UTILS_SOC_TEGRA124,
33}; 34};
34 35
35struct tegra_asoc_utils_data { 36struct tegra_asoc_utils_data {