Loading sound/soc/tegra/tegra30_ahub.c +101 −14 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, { int channel; u32 reg, val; struct tegra30_ahub_cif_conf cif_conf; channel = find_first_zero_bit(ahub->rx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT); Loading @@ -123,15 +124,21 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16; tegra30_apbif_write(reg, val); cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; cif_conf.truncate = 0; cif_conf.mono_conv = 0; reg = TEGRA30_AHUB_CIF_RX_CTRL + (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; tegra30_apbif_write(reg, val); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); return 0; } Loading Loading @@ -183,6 +190,7 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, { int channel; u32 reg, val; struct tegra30_ahub_cif_conf cif_conf; channel = find_first_zero_bit(ahub->tx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT); Loading @@ -206,15 +214,21 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16; tegra30_apbif_write(reg, val); cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; cif_conf.truncate = 0; cif_conf.mono_conv = 0; reg = TEGRA30_AHUB_CIF_TX_CTRL + (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; tegra30_apbif_write(reg, val); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); return 0; } Loading Loading @@ -437,13 +451,21 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { static struct tegra30_ahub_soc_data soc_data_tegra30 = { .clk_list_mask = CLK_LIST_MASK_TEGRA30, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra114 = { .clk_list_mask = CLK_LIST_MASK_TEGRA114, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra124 = { .clk_list_mask = CLK_LIST_MASK_TEGRA114, .set_audio_cif = tegra124_ahub_set_cif, }; static const struct of_device_id tegra30_ahub_of_match[] = { { .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 }, { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 }, { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, {}, Loading Loading @@ -497,6 +519,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, ahub); ahub->soc_data = soc_data; ahub->dev = &pdev->dev; ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); Loading Loading @@ -669,6 +692,70 @@ static struct platform_driver tegra30_ahub_driver = { }; module_platform_driver(tegra30_ahub_driver); void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf) { unsigned int value; value = (conf->threshold << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | ((conf->audio_channels - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | ((conf->client_channels - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | (conf->audio_bits << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | (conf->client_bits << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | (conf->expand << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | (conf->stereo_conv << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | (conf->replicate << TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | (conf->direction << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | (conf->truncate << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | (conf->mono_conv << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); regmap_write(regmap, reg, value); } EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif); void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf) { unsigned int value; value = (conf->threshold << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | ((conf->audio_channels - 1) << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | ((conf->client_channels - 1) << TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | (conf->audio_bits << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | (conf->client_bits << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | (conf->expand << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | (conf->stereo_conv << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | (conf->replicate << TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | (conf->direction << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | (conf->truncate << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | (conf->mono_conv << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); regmap_write(regmap, reg, value); } EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif); MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); MODULE_DESCRIPTION("Tegra30 AHUB driver"); MODULE_LICENSE("GPL v2"); Loading sound/soc/tegra/tegra30_ahub.h +37 −1 Original line number Diff line number Diff line Loading @@ -25,16 +25,30 @@ #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 24 #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0x3f #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) /* Channel count minus 1 */ #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 20 #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 0xf #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16 #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 0xf #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) #define TEGRA30_AUDIOCIF_BITS_4 0 #define TEGRA30_AUDIOCIF_BITS_8 1 #define TEGRA30_AUDIOCIF_BITS_12 2 Loading Loading @@ -86,7 +100,7 @@ #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) #define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3 #define TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT 3 #define TEGRA30_AUDIOCIF_DIRECTION_TX 0 #define TEGRA30_AUDIOCIF_DIRECTION_RX 1 Loading Loading @@ -468,8 +482,30 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif, enum tegra30_ahub_txcif txcif); extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif); struct tegra30_ahub_cif_conf { unsigned int threshold; unsigned int audio_channels; unsigned int client_channels; unsigned int audio_bits; unsigned int client_bits; unsigned int expand; unsigned int stereo_conv; unsigned int replicate; unsigned int direction; unsigned int truncate; unsigned int mono_conv; }; void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); struct tegra30_ahub_soc_data { u32 clk_list_mask; void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); /* * FIXME: There are many more differences in HW, such as: * - More APBIF channels. Loading sound/soc/tegra/tegra30_i2s.c +38 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> Loading Loading @@ -179,6 +180,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); unsigned int mask, val, reg; int ret, sample_size, srate, i2sclock, bitcnt; struct tegra30_ahub_cif_conf cif_conf; if (params_channels(params) != 2) return -EINVAL; Loading Loading @@ -217,21 +219,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16; cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.truncate = 0; cif_conf.mono_conv = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; reg = TEGRA30_I2S_CIF_RX_CTRL; } else { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; reg = TEGRA30_I2S_CIF_TX_CTRL; } regmap_write(i2s->regmap, reg, val); i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf); val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); Loading Loading @@ -396,9 +403,24 @@ static const struct regmap_config tegra30_i2s_regmap_config = { .cache_type = REGCACHE_RBTREE, }; static const struct tegra30_i2s_soc_data tegra30_i2s_config = { .set_audio_cif = tegra30_ahub_set_cif, }; static const struct tegra30_i2s_soc_data tegra124_i2s_config = { .set_audio_cif = tegra124_ahub_set_cif, }; static const struct of_device_id tegra30_i2s_of_match[] = { { .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config }, { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config }, {}, }; static int tegra30_i2s_platform_probe(struct platform_device *pdev) { struct tegra30_i2s *i2s; const struct of_device_id *match; u32 cif_ids[2]; struct resource *mem, *memregion; void __iomem *regs; Loading @@ -412,6 +434,14 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, i2s); match = of_match_device(tegra30_i2s_of_match, &pdev->dev); if (!match) { dev_err(&pdev->dev, "Error: No device match found\n"); ret = -ENODEV; goto err; } i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data; i2s->dai = tegra30_i2s_dai_template; i2s->dai.name = dev_name(&pdev->dev); Loading Loading @@ -539,11 +569,6 @@ static int tegra30_i2s_resume(struct device *dev) } #endif static const struct of_device_id tegra30_i2s_of_match[] = { { .compatible = "nvidia,tegra30-i2s", }, {}, }; static const struct dev_pm_ops tegra30_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, tegra30_i2s_runtime_resume, NULL) Loading sound/soc/tegra/tegra30_i2s.h +7 −0 Original line number Diff line number Diff line Loading @@ -225,7 +225,14 @@ #define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff #define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT) struct tegra30_i2s_soc_data { void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); }; struct tegra30_i2s { const struct tegra30_i2s_soc_data *soc_data; struct snd_soc_dai_driver dai; int cif_id; struct clk *clk_i2s; Loading sound/soc/tegra/tegra_asoc_utils.c +2 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,8 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; else if (of_machine_is_compatible("nvidia,tegra114")) data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; else if (of_machine_is_compatible("nvidia,tegra124")) data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124; else { dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); return -EINVAL; Loading Loading
sound/soc/tegra/tegra30_ahub.c +101 −14 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, { int channel; u32 reg, val; struct tegra30_ahub_cif_conf cif_conf; channel = find_first_zero_bit(ahub->rx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT); Loading @@ -123,15 +124,21 @@ int tegra30_ahub_allocate_rx_fifo(enum tegra30_ahub_rxcif *rxcif, TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16; tegra30_apbif_write(reg, val); cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; cif_conf.truncate = 0; cif_conf.mono_conv = 0; reg = TEGRA30_AHUB_CIF_RX_CTRL + (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; tegra30_apbif_write(reg, val); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); return 0; } Loading Loading @@ -183,6 +190,7 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, { int channel; u32 reg, val; struct tegra30_ahub_cif_conf cif_conf; channel = find_first_zero_bit(ahub->tx_usage, TEGRA30_AHUB_CHANNEL_CTRL_COUNT); Loading @@ -206,15 +214,21 @@ int tegra30_ahub_allocate_tx_fifo(enum tegra30_ahub_txcif *txcif, TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16; tegra30_apbif_write(reg, val); cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; cif_conf.truncate = 0; cif_conf.mono_conv = 0; reg = TEGRA30_AHUB_CIF_TX_CTRL + (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 | TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; tegra30_apbif_write(reg, val); ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf); return 0; } Loading Loading @@ -437,13 +451,21 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { static struct tegra30_ahub_soc_data soc_data_tegra30 = { .clk_list_mask = CLK_LIST_MASK_TEGRA30, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra114 = { .clk_list_mask = CLK_LIST_MASK_TEGRA114, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra124 = { .clk_list_mask = CLK_LIST_MASK_TEGRA114, .set_audio_cif = tegra124_ahub_set_cif, }; static const struct of_device_id tegra30_ahub_of_match[] = { { .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 }, { .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 }, { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, {}, Loading Loading @@ -497,6 +519,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, ahub); ahub->soc_data = soc_data; ahub->dev = &pdev->dev; ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio"); Loading Loading @@ -669,6 +692,70 @@ static struct platform_driver tegra30_ahub_driver = { }; module_platform_driver(tegra30_ahub_driver); void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf) { unsigned int value; value = (conf->threshold << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | ((conf->audio_channels - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | ((conf->client_channels - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | (conf->audio_bits << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | (conf->client_bits << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | (conf->expand << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | (conf->stereo_conv << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | (conf->replicate << TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | (conf->direction << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | (conf->truncate << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | (conf->mono_conv << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); regmap_write(regmap, reg, value); } EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif); void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf) { unsigned int value; value = (conf->threshold << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | ((conf->audio_channels - 1) << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | ((conf->client_channels - 1) << TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | (conf->audio_bits << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) | (conf->client_bits << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) | (conf->expand << TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) | (conf->stereo_conv << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) | (conf->replicate << TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) | (conf->direction << TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) | (conf->truncate << TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) | (conf->mono_conv << TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT); regmap_write(regmap, reg, value); } EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif); MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); MODULE_DESCRIPTION("Tegra30 AHUB driver"); MODULE_LICENSE("GPL v2"); Loading
sound/soc/tegra/tegra30_ahub.h +37 −1 Original line number Diff line number Diff line Loading @@ -25,16 +25,30 @@ #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0xf #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT 24 #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US 0x3f #define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK (TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) /* Channel count minus 1 */ #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 24 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 7 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT 20 #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US 0xf #define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK (TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 7 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) /* Channel count minus 1 */ #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT 16 #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US 0xf #define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK (TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) #define TEGRA30_AUDIOCIF_BITS_4 0 #define TEGRA30_AUDIOCIF_BITS_8 1 #define TEGRA30_AUDIOCIF_BITS_12 2 Loading Loading @@ -86,7 +100,7 @@ #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1 (TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG (TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) #define TEGRA30_AUDIOCIF_CTRL_REPLICATE 3 #define TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT 3 #define TEGRA30_AUDIOCIF_DIRECTION_TX 0 #define TEGRA30_AUDIOCIF_DIRECTION_RX 1 Loading Loading @@ -468,8 +482,30 @@ extern int tegra30_ahub_set_rx_cif_source(enum tegra30_ahub_rxcif rxcif, enum tegra30_ahub_txcif txcif); extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif); struct tegra30_ahub_cif_conf { unsigned int threshold; unsigned int audio_channels; unsigned int client_channels; unsigned int audio_bits; unsigned int client_bits; unsigned int expand; unsigned int stereo_conv; unsigned int replicate; unsigned int direction; unsigned int truncate; unsigned int mono_conv; }; void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); struct tegra30_ahub_soc_data { u32 clk_list_mask; void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); /* * FIXME: There are many more differences in HW, such as: * - More APBIF channels. Loading
sound/soc/tegra/tegra30_i2s.c +38 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> Loading Loading @@ -179,6 +180,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); unsigned int mask, val, reg; int ret, sample_size, srate, i2sclock, bitcnt; struct tegra30_ahub_cif_conf cif_conf; if (params_channels(params) != 2) return -EINVAL; Loading Loading @@ -217,21 +219,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) | TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 | TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16; cif_conf.threshold = 0; cif_conf.audio_channels = 2; cif_conf.client_channels = 2; cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16; cif_conf.expand = 0; cif_conf.stereo_conv = 0; cif_conf.replicate = 0; cif_conf.truncate = 0; cif_conf.mono_conv = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX; reg = TEGRA30_I2S_CIF_RX_CTRL; } else { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX; reg = TEGRA30_I2S_CIF_TX_CTRL; } regmap_write(i2s->regmap, reg, val); i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf); val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); Loading Loading @@ -396,9 +403,24 @@ static const struct regmap_config tegra30_i2s_regmap_config = { .cache_type = REGCACHE_RBTREE, }; static const struct tegra30_i2s_soc_data tegra30_i2s_config = { .set_audio_cif = tegra30_ahub_set_cif, }; static const struct tegra30_i2s_soc_data tegra124_i2s_config = { .set_audio_cif = tegra124_ahub_set_cif, }; static const struct of_device_id tegra30_i2s_of_match[] = { { .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config }, { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config }, {}, }; static int tegra30_i2s_platform_probe(struct platform_device *pdev) { struct tegra30_i2s *i2s; const struct of_device_id *match; u32 cif_ids[2]; struct resource *mem, *memregion; void __iomem *regs; Loading @@ -412,6 +434,14 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, i2s); match = of_match_device(tegra30_i2s_of_match, &pdev->dev); if (!match) { dev_err(&pdev->dev, "Error: No device match found\n"); ret = -ENODEV; goto err; } i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data; i2s->dai = tegra30_i2s_dai_template; i2s->dai.name = dev_name(&pdev->dev); Loading Loading @@ -539,11 +569,6 @@ static int tegra30_i2s_resume(struct device *dev) } #endif static const struct of_device_id tegra30_i2s_of_match[] = { { .compatible = "nvidia,tegra30-i2s", }, {}, }; static const struct dev_pm_ops tegra30_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, tegra30_i2s_runtime_resume, NULL) Loading
sound/soc/tegra/tegra30_i2s.h +7 −0 Original line number Diff line number Diff line Loading @@ -225,7 +225,14 @@ #define TEGRA30_I2S_LCOEF_COEF_MASK_US 0xffff #define TEGRA30_I2S_LCOEF_COEF_MASK (TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT) struct tegra30_i2s_soc_data { void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); }; struct tegra30_i2s { const struct tegra30_i2s_soc_data *soc_data; struct snd_soc_dai_driver dai; int cif_id; struct clk *clk_i2s; Loading
sound/soc/tegra/tegra_asoc_utils.c +2 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,8 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; else if (of_machine_is_compatible("nvidia,tegra114")) data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; else if (of_machine_is_compatible("nvidia,tegra124")) data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124; else { dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); return -EINVAL; Loading