ASoC: tegra-alt: Update codec drivers

1. Remove replicate bit and add fifo_size_downshift bit
   in cif
2. Update mask value for dma_fifo_size, dma_fifo_start_addr
   and dma_fifo_threshold in admaif driver
3. Update the copyright
4. Add run time check function to detect FPGA

Bug 1582514
Bug 1582510

Change-Id: I40a8172ebc3713ead4cb5764f291f04d548c7a75
Signed-off-by: Junghyun Kim <juskim@nvidia.com>
Reviewed-on: http://git-master/r/751602
Reviewed-by: Arun Shamanna Lakshmi <aruns@nvidia.com>
Tested-by: Arun Shamanna Lakshmi <aruns@nvidia.com>
This commit is contained in:
Junghyun Kim
2015-06-01 17:22:57 -07:00
committed by Sameer Pujar
parent 529ec76bea
commit ee8192fe65
14 changed files with 583 additions and 444 deletions

View File

@@ -1,6 +1,6 @@
config SND_SOC_TEGRA_ALT config SND_SOC_TEGRA_ALT
tristate "Alternative DAPM-based SoC audio support for the Tegra System-on-Chip" tristate "Alternative DAPM-based SoC audio support for the Tegra System-on-Chip"
depends on ARCH_TEGRA depends on ARCH_TEGRA || PLATFORM_TEGRA
select REGMAP_MMIO select REGMAP_MMIO
select SND_DMAENGINE_PCM select SND_DMAENGINE_PCM
help help

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_admaif_alt.c - Tegra ADMAIF driver * tegra210_admaif_alt.c - Tegra ADMAIF driver
* *
* Copyright (c) 2015 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -33,6 +33,9 @@
#include "tegra_pcm_alt.h" #include "tegra_pcm_alt.h"
#include "tegra210_xbar_alt.h" #include "tegra210_xbar_alt.h"
#include "tegra210_admaif_alt.h" #include "tegra210_admaif_alt.h"
#if defined(CONFIG_ARCH_TEGRA_18x_SOC)
#include <sound/tegra_audio.h>
#endif
#define DRV_NAME "tegra210-ape-admaif" #define DRV_NAME "tegra210-ape-admaif"
@@ -46,17 +49,47 @@
{ ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_TX_FIFO_CTRL, id), tx_fifo_ctrl} { ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_TX_FIFO_CTRL, id), tx_fifo_ctrl}
static const struct reg_default tegra210_admaif_reg_defaults[] = { static const struct reg_default tegra210_admaif_reg_defaults[] = {
ADMAIF_REG_DEFAULTS(0, 0x00000300, 0x02000300), { TEGRA210_ADMAIF_GLOBAL_CG_0, 0x00000003},
ADMAIF_REG_DEFAULTS(1, 0x00000304, 0x02000304), ADMAIF_REG_DEFAULTS(0, ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT,
ADMAIF_REG_DEFAULTS(2, 0x00000208, 0x01800208), ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(3, 0x0000020b, 0x0180020b), ADMAIF_REG_DEFAULTS(1, ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT,
ADMAIF_REG_DEFAULTS(4, 0x0000020e, 0x0180020e), ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(5, 0x00000211, 0x01800211), ADMAIF_REG_DEFAULTS(2, ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT,
ADMAIF_REG_DEFAULTS(6, 0x00000214, 0x01800214), ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(7, 0x00000217, 0x01800217), ADMAIF_REG_DEFAULTS(3, ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT,
ADMAIF_REG_DEFAULTS(8, 0x0000021a, 0x0180021a), ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(9, 0x0000021d, 0x0180021d), ADMAIF_REG_DEFAULTS(4, ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT,
{ TEGRA210_ADMAIF_GLOBAL_CG_0, 0x00000003} ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(5, ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(6, ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(7, ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(8, ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(9, ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(10, ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(11, ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(12, ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(13, ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(14, ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(15, ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(16, ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(17, ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(18, ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT),
ADMAIF_REG_DEFAULTS(19, ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT,
ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT),
}; };
static bool tegra210_admaif_wr_reg(struct device *dev, unsigned int reg) static bool tegra210_admaif_wr_reg(struct device *dev, unsigned int reg)
@@ -134,7 +167,7 @@ static const struct regmap_config tegra210_admaif_regmap_config = {
.readable_reg = tegra210_admaif_rd_reg, .readable_reg = tegra210_admaif_rd_reg,
.volatile_reg = tegra210_admaif_volatile_reg, .volatile_reg = tegra210_admaif_volatile_reg,
.reg_defaults = tegra210_admaif_reg_defaults, .reg_defaults = tegra210_admaif_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(tegra210_admaif_reg_defaults), .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
@@ -266,15 +299,26 @@ static int tegra210_admaif_hw_params(struct snd_pcm_substream *substream,
unsigned int reg, fifo_ctrl, fifo_size; unsigned int reg, fifo_ctrl, fifo_size;
int valid_bit; int valid_bit;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
cif_conf.audio_channels = params_channels(params); cif_conf.audio_channels = params_channels(params);
cif_conf.client_channels = params_channels(params); cif_conf.client_channels = params_channels(params);
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_8;
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_8;
valid_bit = DATA_8BIT;
break;
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_16; cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_16;
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_16; cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_16;
valid_bit = DATA_16BIT; valid_bit = DATA_16BIT;
break; break;
case SNDRV_PCM_FORMAT_S24_LE:
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_24;
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24;
valid_bit = DATA_32BIT;
break;
case SNDRV_PCM_FORMAT_S32_LE: case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_32; cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_32;
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32; cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
@@ -285,13 +329,6 @@ static int tegra210_admaif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
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) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
reg = TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL + reg = TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL +
(dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE); (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
@@ -462,7 +499,7 @@ static int tegra210_admaif_dai_probe(struct snd_soc_dai *dai)
.ops = &tegra210_admaif_dai_ops, \ .ops = &tegra210_admaif_dai_ops, \
} }
static struct snd_soc_dai_driver tegra210_admaif_dais[10] = { static struct snd_soc_dai_driver tegra210_admaif_dais[] = {
ADMAIF_DAI(1), ADMAIF_DAI(1),
ADMAIF_DAI(2), ADMAIF_DAI(2),
ADMAIF_DAI(3), ADMAIF_DAI(3),
@@ -473,6 +510,16 @@ static struct snd_soc_dai_driver tegra210_admaif_dais[10] = {
ADMAIF_DAI(8), ADMAIF_DAI(8),
ADMAIF_DAI(9), ADMAIF_DAI(9),
ADMAIF_DAI(10), ADMAIF_DAI(10),
ADMAIF_DAI(11),
ADMAIF_DAI(12),
ADMAIF_DAI(13),
ADMAIF_DAI(14),
ADMAIF_DAI(15),
ADMAIF_DAI(16),
ADMAIF_DAI(17),
ADMAIF_DAI(18),
ADMAIF_DAI(19),
ADMAIF_DAI(20),
}; };
#define ADMAIF_CODEC_FIFO_DAI(id) \ #define ADMAIF_CODEC_FIFO_DAI(id) \
@@ -547,6 +594,26 @@ static struct snd_soc_dai_driver tegra210_admaif_codec_dais[] = {
ADMAIF_CODEC_CIF_DAI(8), ADMAIF_CODEC_CIF_DAI(8),
ADMAIF_CODEC_CIF_DAI(9), ADMAIF_CODEC_CIF_DAI(9),
ADMAIF_CODEC_CIF_DAI(10), ADMAIF_CODEC_CIF_DAI(10),
ADMAIF_CODEC_FIFO_DAI(11),
ADMAIF_CODEC_FIFO_DAI(12),
ADMAIF_CODEC_FIFO_DAI(13),
ADMAIF_CODEC_FIFO_DAI(14),
ADMAIF_CODEC_FIFO_DAI(15),
ADMAIF_CODEC_FIFO_DAI(16),
ADMAIF_CODEC_FIFO_DAI(17),
ADMAIF_CODEC_FIFO_DAI(18),
ADMAIF_CODEC_FIFO_DAI(19),
ADMAIF_CODEC_FIFO_DAI(20),
ADMAIF_CODEC_CIF_DAI(11),
ADMAIF_CODEC_CIF_DAI(12),
ADMAIF_CODEC_CIF_DAI(13),
ADMAIF_CODEC_CIF_DAI(14),
ADMAIF_CODEC_CIF_DAI(15),
ADMAIF_CODEC_CIF_DAI(16),
ADMAIF_CODEC_CIF_DAI(17),
ADMAIF_CODEC_CIF_DAI(18),
ADMAIF_CODEC_CIF_DAI(19),
ADMAIF_CODEC_CIF_DAI(20),
}; };
#define ADMAIF_WIDGETS(id) \ #define ADMAIF_WIDGETS(id) \
@@ -569,7 +636,17 @@ static const struct snd_soc_dapm_widget tegra210_admaif_widgets[] = {
ADMAIF_WIDGETS(7), ADMAIF_WIDGETS(7),
ADMAIF_WIDGETS(8), ADMAIF_WIDGETS(8),
ADMAIF_WIDGETS(9), ADMAIF_WIDGETS(9),
ADMAIF_WIDGETS(10) ADMAIF_WIDGETS(10),
ADMAIF_WIDGETS(11),
ADMAIF_WIDGETS(12),
ADMAIF_WIDGETS(13),
ADMAIF_WIDGETS(14),
ADMAIF_WIDGETS(15),
ADMAIF_WIDGETS(16),
ADMAIF_WIDGETS(17),
ADMAIF_WIDGETS(18),
ADMAIF_WIDGETS(19),
ADMAIF_WIDGETS(20)
}; };
#define ADMAIF_ROUTES(id) \ #define ADMAIF_ROUTES(id) \
@@ -590,7 +667,17 @@ static const struct snd_soc_dapm_route tegra210_admaif_routes[] = {
ADMAIF_ROUTES(7), ADMAIF_ROUTES(7),
ADMAIF_ROUTES(8), ADMAIF_ROUTES(8),
ADMAIF_ROUTES(9), ADMAIF_ROUTES(9),
ADMAIF_ROUTES(10) ADMAIF_ROUTES(10),
ADMAIF_ROUTES(11),
ADMAIF_ROUTES(12),
ADMAIF_ROUTES(13),
ADMAIF_ROUTES(14),
ADMAIF_ROUTES(15),
ADMAIF_ROUTES(16),
ADMAIF_ROUTES(17),
ADMAIF_ROUTES(18),
ADMAIF_ROUTES(19),
ADMAIF_ROUTES(20)
}; };
static int tegra210_admaif_codec_probe(struct snd_soc_codec *codec) static int tegra210_admaif_codec_probe(struct snd_soc_codec *codec)
@@ -605,9 +692,9 @@ static int tegra210_admaif_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver tegra210_admaif_codec = { static struct snd_soc_codec_driver tegra210_admaif_codec = {
.probe = tegra210_admaif_codec_probe, .probe = tegra210_admaif_codec_probe,
.dapm_widgets = tegra210_admaif_widgets, .dapm_widgets = tegra210_admaif_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra210_admaif_widgets), .num_dapm_widgets = TEGRA210_ADMAIF_CHANNEL_COUNT * 4,
.dapm_routes = tegra210_admaif_routes, .dapm_routes = tegra210_admaif_routes,
.num_dapm_routes = ARRAY_SIZE(tegra210_admaif_routes), .num_dapm_routes = TEGRA210_ADMAIF_CHANNEL_COUNT * 6,
.idle_bias_off = 1, .idle_bias_off = 1,
}; };
@@ -616,7 +703,7 @@ static const struct snd_soc_component_driver tegra210_admaif_dai_driver = {
}; };
static struct tegra210_admaif_soc_data soc_data_tegra210 = { static struct tegra210_admaif_soc_data soc_data_tegra210 = {
.num_ch = 10, .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
.set_audio_cif = tegra210_xbar_set_cif, .set_audio_cif = tegra210_xbar_set_cif,
}; };
@@ -745,7 +832,7 @@ static int tegra210_admaif_probe(struct platform_device *pdev)
ret = snd_soc_register_component(&pdev->dev, ret = snd_soc_register_component(&pdev->dev,
&tegra210_admaif_dai_driver, &tegra210_admaif_dai_driver,
tegra210_admaif_dais, tegra210_admaif_dais,
ARRAY_SIZE(tegra210_admaif_dais)); admaif->soc_data->num_ch);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Could not register DAIs %d: %d\n", dev_err(&pdev->dev, "Could not register DAIs %d: %d\n",
i, ret); i, ret);
@@ -755,7 +842,7 @@ static int tegra210_admaif_probe(struct platform_device *pdev)
ret = snd_soc_register_codec(&pdev->dev, &tegra210_admaif_codec, ret = snd_soc_register_codec(&pdev->dev, &tegra210_admaif_codec,
tegra210_admaif_codec_dais, tegra210_admaif_codec_dais,
ARRAY_SIZE(tegra210_admaif_codec_dais)); admaif->soc_data->num_ch * 2);
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret); dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
goto err_unregister_dais; goto err_unregister_dais;

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_adx_alt.c - Tegra210 ADX driver * tegra210_adx_alt.c - Tegra210 ADX driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -26,6 +26,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tegra-soc.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@@ -290,6 +291,8 @@ static int tegra210_adx_set_audio_cif(struct tegra210_adx *adx,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 1 || channels > 16) if (channels < 1 || channels > 16)
return -EINVAL; return -EINVAL;
@@ -311,16 +314,10 @@ static int tegra210_adx_set_audio_cif(struct tegra210_adx *adx,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
adx->soc_data->set_audio_cif(adx->regmap, reg, &cif_conf); adx->soc_data->set_audio_cif(adx->regmap, reg, &cif_conf);
@@ -372,6 +369,12 @@ static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai); struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
int ret; int ret;
if (tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()) {
/* update the map ram */
tegra210_adx_update_map_ram(adx);
tegra210_adx_set_in_byte_mask(adx);
}
ret = tegra210_adx_set_audio_cif(adx, params, ret = tegra210_adx_set_audio_cif(adx, params,
TEGRA210_ADX_AXBAR_RX_CIF_CTRL); TEGRA210_ADX_AXBAR_RX_CIF_CTRL);
return ret; return ret;
@@ -414,7 +417,7 @@ static int tegra210_adx_set_channel_map(struct snd_soc_dai *dai,
out_byte_idx); out_byte_idx);
/* making byte_mask */ /* making byte_mask */
if (i > 32) if (i > 31)
adx->byte_mask[1] |= (1 << (i - 32)); adx->byte_mask[1] |= (1 << (i - 32));
else else
adx->byte_mask[0] |= (1 << i); adx->byte_mask[0] |= (1 << i);

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_afc_alt.c - Tegra210 AFC driver * tegra210_afc_alt.c - Tegra210 AFC driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -34,6 +34,9 @@
#include "tegra210_xbar_alt.h" #include "tegra210_xbar_alt.h"
#include "tegra210_afc_alt.h" #include "tegra210_afc_alt.h"
#if defined(CONFIG_ARCH_TEGRA_18x_SOC)
#include <sound/tegra_audio.h>
#endif
#define DRV_NAME "tegra210-afc" #define DRV_NAME "tegra210-afc"
@@ -57,7 +60,6 @@ static const struct reg_default tegra210_afc_reg_defaults[] = {
{ TEGRA210_AFC_LCOEF_2_4_2, 0x00004c07}, { TEGRA210_AFC_LCOEF_2_4_2, 0x00004c07},
}; };
static int tegra210_afc_runtime_suspend(struct device *dev) static int tegra210_afc_runtime_suspend(struct device *dev)
{ {
struct tegra210_afc *afc = dev_get_drvdata(dev); struct tegra210_afc *afc = dev_get_drvdata(dev);
@@ -96,20 +98,44 @@ static int tegra210_afc_suspend(struct device *dev)
} }
#endif #endif
static void tegra210_afc_set_ppm_diff(struct tegra210_afc *afc,
unsigned int ppm_diff)
{
regmap_update_bits(afc->regmap,
TEGRA210_AFC_CLK_PPM_DIFF, 0xFFFF, ppm_diff);
}
/* returns the id if SFC is connected along the AFC src path */
unsigned int tegra210_afc_get_sfc_id(unsigned int afc_id)
{
unsigned int reg, val = 0;
reg = TEGRA210_XBAR_PART0_RX +
TEGRA210_XBAR_RX_STRIDE *
(afc_id + XBAR_AFC_REG_OFFSET_DIVIDED_BY_4);
tegra210_xbar_read_reg(reg, &val);
val = val >> 24;
return val;
}
EXPORT_SYMBOL_GPL(tegra210_afc_get_sfc_id);
#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
/* returns the destination I2S id connected along the AFC path */ /* returns the destination I2S id connected along the AFC path */
static unsigned int tegra210_afc_get_i2s_id(unsigned int afc_id) static unsigned int tegra210_afc_get_i2s_id(unsigned int afc_id)
{ {
unsigned int i2s_reg, i2s_val, amx_reg, amx_val, i, j; unsigned int i2s_reg, i2s_val, amx_reg, amx_val, i, j;
for (i = 1; i < 6; i++) { for (i = 1; i < MAX_NUM_I2S; i++) {
i2s_val = 0; i2s_val = 0;
i2s_reg = TEGRA210_XBAR_PART1_RX + i2s_reg = TEGRA210_XBAR_PART1_RX +
TEGRA210_XBAR_RX_STRIDE * (i + 0xF); TEGRA210_XBAR_RX_STRIDE * (i + 0xF);
tegra210_xbar_read_reg(i2s_reg, &i2s_val); tegra210_xbar_read_reg(i2s_reg, &i2s_val);
if ((i2s_val >> 24) & (1 << afc_id)) { if ((i2s_val >> 24) & (1 << afc_id)) {
return i; return i;
} else if (i2s_val & 0x300) { } else if (i2s_val & MASK_AMX_TX) {
for (j = 1; j < 9; j++) { for (j = 1; j < 9; j++) { /* AMX1/2 */
amx_val = 0; amx_val = 0;
amx_reg = TEGRA210_XBAR_PART1_RX + amx_reg = TEGRA210_XBAR_PART1_RX +
TEGRA210_XBAR_RX_STRIDE * (j + 0x4F); TEGRA210_XBAR_RX_STRIDE * (j + 0x4F);
@@ -119,28 +145,7 @@ static unsigned int tegra210_afc_get_i2s_id(unsigned int afc_id)
} }
} }
} }
return 1; return 0;
}
/* returns the id if SFC is connected along the AFC src path */
static unsigned int tegra210_afc_get_sfc_id(unsigned int afc_id)
{
unsigned int reg, val = 0;
reg = TEGRA210_XBAR_PART0_RX +
TEGRA210_XBAR_RX_STRIDE * (afc_id + 0x34);
tegra210_xbar_read_reg(reg, &val);
val = val >> 24;
return val;
}
static void tegra210_afc_set_ppm_diff(struct tegra210_afc *afc,
unsigned int ppm_diff)
{
regmap_update_bits(afc->regmap,
TEGRA210_AFC_CLK_PPM_DIFF, 0xFFFF, ppm_diff);
} }
static int tegra210_afc_set_thresholds(struct tegra210_afc *afc, static int tegra210_afc_set_thresholds(struct tegra210_afc *afc,
@@ -158,13 +163,15 @@ static int tegra210_afc_set_thresholds(struct tegra210_afc *afc,
regmap_write(afc->regmap, TEGRA210_AFC_TXCIF_FIFO_PARAMS, value); regmap_write(afc->regmap, TEGRA210_AFC_TXCIF_FIFO_PARAMS, value);
i2s_id = tegra210_afc_get_i2s_id(afc_id); i2s_id = tegra210_afc_get_i2s_id(afc_id);
if (!i2s_id)
return -EINVAL;
value |= i2s_id << TEGRA210_AFC_DEST_I2S_ID_SHIFT; value |= CONFIG_AFC_DEST_PARAM(0, i2s_id);
SET_AFC_DEST_PARAM(value);
regmap_write(afc->regmap, TEGRA210_AFC_DEST_I2S_PARAMS, value);
return 0; return 0;
} }
#endif
static int tegra210_afc_set_audio_cif(struct tegra210_afc *afc, static int tegra210_afc_set_audio_cif(struct tegra210_afc *afc,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
@@ -173,6 +180,8 @@ static int tegra210_afc_set_audio_cif(struct tegra210_afc *afc,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) if (channels < 2)
return -EINVAL; return -EINVAL;
@@ -188,16 +197,10 @@ static int tegra210_afc_set_audio_cif(struct tegra210_afc *afc,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
afc->soc_data->set_audio_cif(afc->regmap, reg, &cif_conf); afc->soc_data->set_audio_cif(afc->regmap, reg, &cif_conf);
@@ -226,10 +229,11 @@ static int tegra210_afc_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
tegra210_afc_set_ppm_diff(afc, 50); tegra210_afc_set_ppm_diff(afc, AFC_CLK_PPM_DIFF);
/* program the thresholds, destn i2s id, PPM values */ /* program the thresholds, destn i2s id, PPM values */
tegra210_afc_set_thresholds(afc, dev->id); if (tegra210_afc_set_thresholds(afc, dev->id) == -EINVAL)
dev_err(dev, "Can't set AFC threshold: %d\n", ret);
return ret; return ret;
@@ -445,7 +449,6 @@ static int tegra210_afc_platform_probe(struct platform_device *pdev)
/* Disable SLGC */ /* Disable SLGC */
regmap_write(afc->regmap, TEGRA210_AFC_CG, 0); regmap_write(afc->regmap, TEGRA210_AFC_CG, 0);
regcache_cache_only(afc->regmap, true);
ret = snd_soc_register_codec(&pdev->dev, &tegra210_afc_codec, ret = snd_soc_register_codec(&pdev->dev, &tegra210_afc_codec,
tegra210_afc_dais, tegra210_afc_dais,

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_amx_alt.c - Tegra210 AMX driver * tegra210_amx_alt.c - Tegra210 AMX driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -26,6 +26,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tegra-soc.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@@ -155,7 +156,6 @@ static void tegra210_amx_write_map_ram(struct tegra210_amx *amx,
unsigned int val) unsigned int val)
{ {
unsigned int reg; unsigned int reg;
regmap_write(amx->regmap, TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL, regmap_write(amx->regmap, TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL,
(addr << TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL_RAM_ADDR_SHIFT)); (addr << TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL_RAM_ADDR_SHIFT));
@@ -318,6 +318,8 @@ static int tegra210_amx_set_audio_cif(struct tegra210_amx *amx,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 1 || channels > 16) if (channels < 1 || channels > 16)
return -EINVAL; return -EINVAL;
@@ -339,16 +341,10 @@ static int tegra210_amx_set_audio_cif(struct tegra210_amx *amx,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
amx->soc_data->set_audio_cif(amx->regmap, reg, &cif_conf); amx->soc_data->set_audio_cif(amx->regmap, reg, &cif_conf);
@@ -400,6 +396,13 @@ static int tegra210_amx_out_hw_params(struct snd_pcm_substream *substream,
{ {
struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai); struct tegra210_amx *amx = snd_soc_dai_get_drvdata(dai);
int ret; int ret;
if (tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()) {
/* update map ram */
tegra210_amx_set_master_stream(amx, 0,
TEGRA210_AMX_WAIT_ON_ANY);
tegra210_amx_update_map_ram(amx);
tegra210_amx_set_out_byte_mask(amx);
}
ret = tegra210_amx_set_audio_cif(amx, params, ret = tegra210_amx_set_audio_cif(amx, params,
TEGRA210_AMX_AXBAR_TX_CIF_CTRL); TEGRA210_AMX_AXBAR_TX_CIF_CTRL);
@@ -444,7 +447,7 @@ static int tegra210_amx_set_channel_map(struct snd_soc_dai *dai,
in_byte_idx); in_byte_idx);
/* making byte_mask */ /* making byte_mask */
if (i > 32) if (i > 31)
amx->byte_mask[1] |= (1 << (i - 32)); amx->byte_mask[1] |= (1 << (i - 32));
else else
amx->byte_mask[0] |= (1 << i); amx->byte_mask[0] |= (1 << i);

View File

@@ -24,6 +24,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tegra-soc.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@@ -73,9 +74,9 @@ static int tegra210_dmic_runtime_suspend(struct device *dev)
struct tegra210_dmic *dmic = dev_get_drvdata(dev); struct tegra210_dmic *dmic = dev_get_drvdata(dev);
regcache_cache_only(dmic->regmap, true); regcache_cache_only(dmic->regmap, true);
#ifndef CONFIG_MACH_GRENADA if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
clk_disable_unprepare(dmic->clk_dmic); clk_disable_unprepare(dmic->clk_dmic);
#endif
pm_runtime_put_sync(dev->parent); pm_runtime_put_sync(dev->parent);
return 0; return 0;
@@ -92,13 +93,13 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
return ret; return ret;
} }
#ifndef CONFIG_MACH_GRENADA if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
ret = clk_prepare_enable(dmic->clk_dmic); ret = clk_prepare_enable(dmic->clk_dmic);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
return ret; return ret;
} }
#endif }
regcache_cache_only(dmic->regmap, false); regcache_cache_only(dmic->regmap, false);
regcache_sync(dmic->regmap); regcache_sync(dmic->regmap);
@@ -125,14 +126,16 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
int channels, srate, dmic_clk, osr = TEGRA210_DMIC_OSR_64; int channels, srate, dmic_clk, osr = TEGRA210_DMIC_OSR_64;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
srate = params_rate(params); srate = params_rate(params);
dmic_clk = (1 << (6+osr)) * (srate/2); dmic_clk = (1 << (6+osr)) * (srate/2);
#ifdef CONFIG_MACH_GRENADA if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
program_dmic_gpio(); program_dmic_gpio();
program_dmic_clk(dmic_clk); program_dmic_clk(dmic_clk);
#endif }
regmap_update_bits(dmic->regmap, regmap_update_bits(dmic->regmap,
TEGRA210_DMIC_CTRL, TEGRA210_DMIC_CTRL,
@@ -150,7 +153,6 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
((1 << channels) - 1) << ((1 << channels) - 1) <<
TEGRA210_DMIC_CTRL_CHANNEL_SELECT_SHIFT); TEGRA210_DMIC_CTRL_CHANNEL_SELECT_SHIFT);
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
@@ -167,11 +169,6 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
} }
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24; cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
dmic->soc_data->set_audio_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, dmic->soc_data->set_audio_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL,
&cif_conf); &cif_conf);
@@ -358,12 +355,14 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
dmic->soc_data = soc_data; dmic->soc_data = soc_data;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL); dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dmic->clk_dmic)) { if (IS_ERR(dmic->clk_dmic)) {
dev_err(&pdev->dev, "Can't retrieve dmic clock\n"); dev_err(&pdev->dev, "Can't retrieve dmic clock\n");
ret = PTR_ERR(dmic->clk_dmic); ret = PTR_ERR(dmic->clk_dmic);
goto err; goto err;
} }
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {
@@ -430,6 +429,7 @@ err_suspend:
err_pm_disable: err_pm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
err_clk_put: err_clk_put:
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
devm_clk_put(&pdev->dev, dmic->clk_dmic); devm_clk_put(&pdev->dev, dmic->clk_dmic);
err: err:
return ret; return ret;

View File

@@ -37,7 +37,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/tegra-powergate.h> #include <linux/tegra-powergate.h>
#include <linux/tegra-soc.h>
#include "tegra210_xbar_alt.h" #include "tegra210_xbar_alt.h"
#include "tegra210_i2s_alt.h" #include "tegra210_i2s_alt.h"
@@ -69,10 +69,11 @@ static int tegra210_i2s_set_clock_rate(struct device *dev, int clock_rate)
{ {
unsigned int val; unsigned int val;
struct tegra210_i2s *i2s = dev_get_drvdata(dev); struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int ret; int ret = 0;
regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if ((val & TEGRA210_I2S_CTRL_MASTER_EN_MASK) == if ((val & TEGRA210_I2S_CTRL_MASTER_EN_MASK) ==
TEGRA210_I2S_CTRL_MASTER_EN) { TEGRA210_I2S_CTRL_MASTER_EN) {
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0); ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
@@ -83,7 +84,8 @@ static int tegra210_i2s_set_clock_rate(struct device *dev, int clock_rate)
ret = clk_set_rate(i2s->clk_i2s, clock_rate); ret = clk_set_rate(i2s->clk_i2s, clock_rate);
if (ret) { if (ret) {
dev_err(dev, "Can't set I2S clock rate: %d\n", ret); dev_err(dev,
"Can't set I2S clock rate: %d\n", ret);
return ret; return ret;
} }
} else { } else {
@@ -101,10 +103,12 @@ static int tegra210_i2s_set_clock_rate(struct device *dev, int clock_rate)
ret = clk_set_rate(i2s->clk_i2s, clock_rate); ret = clk_set_rate(i2s->clk_i2s, clock_rate);
if (ret) { if (ret) {
dev_err(dev, "Can't set I2S clock rate: %d\n", ret); dev_err(dev,
"Can't set I2S clock rate: %d\n", ret);
return ret; return ret;
} }
} }
}
return ret; return ret;
} }
@@ -160,8 +164,8 @@ static int tegra210_i2s_get_status(struct tegra210_i2s *i2s,
unsigned int status_reg, val; unsigned int status_reg, val;
status_reg = (direction == SNDRV_PCM_STREAM_PLAYBACK) ? status_reg = (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
TEGRA210_I2S_AXBAR_TX_STATUS : TEGRA210_I2S_AXBAR_RX_STATUS :
TEGRA210_I2S_AXBAR_RX_STATUS; TEGRA210_I2S_AXBAR_TX_STATUS;
regmap_read(i2s->regmap, status_reg, &val); regmap_read(i2s->regmap, status_reg, &val);
val = val & 0x00000001; val = val & 0x00000001;
@@ -220,8 +224,10 @@ static int tegra210_i2s_runtime_suspend(struct device *dev)
struct tegra210_i2s *i2s = dev_get_drvdata(dev); struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int ret; int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(i2s->pin_idle_state)) { if (!IS_ERR(i2s->pin_idle_state)) {
ret = pinctrl_select_state(i2s->pinctrl, i2s->pin_idle_state); ret = pinctrl_select_state(
i2s->pinctrl, i2s->pin_idle_state);
if (ret < 0) if (ret < 0)
dev_err(dev, "setting dap pinctrl idle state failed\n"); dev_err(dev, "setting dap pinctrl idle state failed\n");
} }
@@ -234,7 +240,11 @@ static int tegra210_i2s_runtime_suspend(struct device *dev)
} }
regcache_cache_only(i2s->regmap, true); regcache_cache_only(i2s->regmap, true);
clk_disable_unprepare(i2s->clk_i2s); clk_disable_unprepare(i2s->clk_i2s);
} else
regcache_cache_only(i2s->regmap, true);
pm_runtime_put_sync(dev->parent); pm_runtime_put_sync(dev->parent);
return 0; return 0;
@@ -251,6 +261,7 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
return ret; return ret;
} }
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(i2s->pin_default_state)) { if (!IS_ERR(i2s->pin_default_state)) {
ret = pinctrl_select_state(i2s->pinctrl, ret = pinctrl_select_state(i2s->pinctrl,
i2s->pin_default_state); i2s->pin_default_state);
@@ -270,6 +281,7 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
return ret; return ret;
} }
}
regcache_cache_only(i2s->regmap, false); regcache_cache_only(i2s->regmap, false);
regcache_sync(i2s->regmap); regcache_sync(i2s->regmap);
@@ -407,6 +419,8 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
int ret, sample_size, channels, srate, i2sclock, bitcnt; int ret, sample_size, channels, srate, i2sclock, bitcnt;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 1) { if (channels < 1) {
dev_err(dev, "Doesn't support %d channels\n", channels); dev_err(dev, "Doesn't support %d channels\n", channels);
@@ -459,20 +473,10 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
cif_conf.threshold = 3; cif_conf.threshold = 3;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
} else { } else {
cif_conf.threshold = 3; cif_conf.threshold = 3;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = (channels == 1) ? 2 : channels; cif_conf.client_channels = (channels == 1) ? 2 : channels;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
} }
i2sclock = srate * sample_size * cif_conf.client_channels; i2sclock = srate * sample_size * cif_conf.client_channels;
@@ -829,6 +833,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
i2s->enable_cya = false; i2s->enable_cya = false;
i2s->loopback = 0; i2s->loopback = 0;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL); i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2s->clk_i2s)) { if (IS_ERR(i2s->clk_i2s)) {
dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
@@ -856,7 +861,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
ret = PTR_ERR(i2s->clk_pll_a_out0); ret = PTR_ERR(i2s->clk_pll_a_out0);
goto err_audio_sync_clk_put; goto err_audio_sync_clk_put;
} }
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {
dev_err(&pdev->dev, "No memory resource\n"); dev_err(&pdev->dev, "No memory resource\n");
@@ -888,8 +893,11 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
} }
i2s->slgc_notifier.notifier_call = _tegra210_i2s_slcg_notifier; i2s->slgc_notifier.notifier_call = _tegra210_i2s_slcg_notifier;
#if defined(CONFIG_ARCH_TEGRA_21X_SOC)
slcg_register_notifier(TEGRA_POWERGATE_APE, slcg_register_notifier(TEGRA_POWERGATE_APE,
&i2s->slgc_notifier); &i2s->slgc_notifier);
#endif
regcache_cache_only(i2s->regmap, true); regcache_cache_only(i2s->regmap, true);
@@ -918,10 +926,12 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
of_property_read_bool(pdev->dev.of_node, of_property_read_bool(pdev->dev.of_node,
"enable-cya"); "enable-cya");
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (of_property_read_string(np, "prod-name", &prod_name) == 0) if (of_property_read_string(np, "prod-name", &prod_name) == 0)
tegra_pinctrl_config_prod(&pdev->dev, prod_name); tegra_pinctrl_config_prod(&pdev->dev, prod_name);
num_supplies = of_property_count_strings(np, "regulator-supplies"); num_supplies =
of_property_count_strings(np, "regulator-supplies");
if (num_supplies > 0) { if (num_supplies > 0) {
i2s->num_supplies = num_supplies; i2s->num_supplies = num_supplies;
i2s->supplies = devm_kzalloc(&pdev->dev, num_supplies * i2s->supplies = devm_kzalloc(&pdev->dev, num_supplies *
@@ -930,11 +940,12 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
ret = -ENOMEM; ret = -ENOMEM;
goto err_pll_a_out0_clk_put; goto err_pll_a_out0_clk_put;
} }
of_property_for_each_string(np, "regulator-supplies", of_property_for_each_string(np,
prop, supply) "regulator-supplies", prop, supply)
i2s->supplies[count++].supply = supply; i2s->supplies[count++].supply = supply;
ret = devm_regulator_bulk_get(&pdev->dev, i2s->num_supplies, ret = devm_regulator_bulk_get(
&pdev->dev, i2s->num_supplies,
i2s->supplies); i2s->supplies);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
@@ -968,7 +979,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "setting state failed\n"); dev_err(&pdev->dev, "setting state failed\n");
goto err_dap; goto err_dap;
} }
}
err_dap: err_dap:
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev)) {
@@ -993,6 +1004,7 @@ err_suspend:
err_pm_disable: err_pm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
err_pll_a_out0_clk_put: err_pll_a_out0_clk_put:
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
clk_put(i2s->clk_pll_a_out0); clk_put(i2s->clk_pll_a_out0);
err_audio_sync_clk_put: err_audio_sync_clk_put:
devm_clk_put(&pdev->dev, i2s->clk_audio_sync); devm_clk_put(&pdev->dev, i2s->clk_audio_sync);
@@ -1014,10 +1026,12 @@ static int tegra210_i2s_platform_remove(struct platform_device *pdev)
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
tegra210_i2s_runtime_suspend(&pdev->dev); tegra210_i2s_runtime_suspend(&pdev->dev);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
devm_clk_put(&pdev->dev, i2s->clk_i2s); devm_clk_put(&pdev->dev, i2s->clk_i2s);
devm_clk_put(&pdev->dev, i2s->clk_audio_sync); devm_clk_put(&pdev->dev, i2s->clk_audio_sync);
devm_clk_put(&pdev->dev, i2s->clk_i2s_sync); devm_clk_put(&pdev->dev, i2s->clk_i2s_sync);
clk_put(i2s->clk_pll_a_out0); clk_put(i2s->clk_pll_a_out0);
}
return 0; return 0;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_iqc.c - Tegra210 IQC driver * tegra210_iqc.c - Tegra210 IQC driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -115,16 +115,11 @@ static int tegra210_iqc_set_audio_cif(struct tegra210_iqc *iqc,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0; memset(cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
iqc->soc_data->set_audio_cif(iqc->regmap, reg, &cif_conf); iqc->soc_data->set_audio_cif(iqc->regmap, reg, &cif_conf);
@@ -349,12 +344,14 @@ static int tegra210_iqc_platform_probe(struct platform_device *pdev)
iqc->soc_data = soc_data; iqc->soc_data = soc_data;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
iqc->clk_iqc = devm_clk_get(&pdev->dev, NULL); iqc->clk_iqc = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(iqc->clk_iqc)) { if (IS_ERR(iqc->clk_iqc)) {
dev_err(&pdev->dev, "Can't retrieve iqc clock\n"); dev_err(&pdev->dev, "Can't retrieve iqc clock\n");
ret = PTR_ERR(iqc->clk_iqc); ret = PTR_ERR(iqc->clk_iqc);
goto err; goto err;
} }
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_mixer_alt.c - Tegra210 MIXER driver * tegra210_mixer_alt.c - Tegra210 MIXER driver
* *
* Copyright (c) 2015 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -196,6 +196,8 @@ static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) if (channels < 2)
return -EINVAL; return -EINVAL;
@@ -211,16 +213,10 @@ static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
mixer->soc_data->set_audio_cif(mixer->regmap, reg, &cif_conf); mixer->soc_data->set_audio_cif(mixer->regmap, reg, &cif_conf);
return 0; return 0;

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_mvc_alt.c - Tegra210 MVC driver * tegra210_mvc_alt.c - Tegra210 MVC driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -170,6 +170,8 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) if (channels < 2)
return -EINVAL; return -EINVAL;
@@ -185,16 +187,10 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
mvc->soc_data->set_audio_cif(mvc->regmap, reg, &cif_conf); mvc->soc_data->set_audio_cif(mvc->regmap, reg, &cif_conf);

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_ope_alt.c - Tegra210 OPE driver * tegra210_ope_alt.c - Tegra210 OPE driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -98,6 +98,8 @@ static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) if (channels < 2)
return -EINVAL; return -EINVAL;
@@ -113,16 +115,10 @@ static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
ope->soc_data->set_audio_cif(ope->regmap, reg, &cif_conf); ope->soc_data->set_audio_cif(ope->regmap, reg, &cif_conf);

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_sfc_alt.c - Tegra210 SFC driver * tegra210_sfc_alt.c - Tegra210 SFC driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -149,6 +149,8 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
int channels, audio_bits; int channels, audio_bits;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) if (channels < 2)
return -EINVAL; return -EINVAL;
@@ -164,16 +166,10 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
return -EINVAL; return -EINVAL;
} }
cif_conf.threshold = 0;
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits; cif_conf.client_bits = audio_bits;
cif_conf.expand = 0;
cif_conf.stereo_conv = 0;
cif_conf.replicate = 0;
cif_conf.truncate = 0;
cif_conf.mono_conv = 0;
sfc->soc_data->set_audio_cif(sfc->regmap, reg, &cif_conf); sfc->soc_data->set_audio_cif(sfc->regmap, reg, &cif_conf);

View File

@@ -25,6 +25,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tegra-soc.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@@ -60,9 +61,11 @@ static int tegra210_spdif_runtime_suspend(struct device *dev)
struct tegra210_spdif *spdif = dev_get_drvdata(dev); struct tegra210_spdif *spdif = dev_get_drvdata(dev);
regcache_cache_only(spdif->regmap, true); regcache_cache_only(spdif->regmap, true);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
clk_disable_unprepare(spdif->clk_spdif_out); clk_disable_unprepare(spdif->clk_spdif_out);
clk_disable_unprepare(spdif->clk_spdif_in); clk_disable_unprepare(spdif->clk_spdif_in);
}
pm_runtime_put_sync(dev->parent); pm_runtime_put_sync(dev->parent);
return 0; return 0;
@@ -71,7 +74,7 @@ static int tegra210_spdif_runtime_suspend(struct device *dev)
static int tegra210_spdif_runtime_resume(struct device *dev) static int tegra210_spdif_runtime_resume(struct device *dev)
{ {
struct tegra210_spdif *spdif = dev_get_drvdata(dev); struct tegra210_spdif *spdif = dev_get_drvdata(dev);
int ret = 0; int ret;
ret = pm_runtime_get_sync(dev->parent); ret = pm_runtime_get_sync(dev->parent);
if (ret < 0) { if (ret < 0) {
@@ -79,6 +82,7 @@ static int tegra210_spdif_runtime_resume(struct device *dev)
return ret; return ret;
} }
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
ret = clk_prepare_enable(spdif->clk_spdif_out); ret = clk_prepare_enable(spdif->clk_spdif_out);
if (ret) { if (ret) {
dev_err(dev, "spdif_out_clk_enable failed: %d\n", ret); dev_err(dev, "spdif_out_clk_enable failed: %d\n", ret);
@@ -90,11 +94,12 @@ static int tegra210_spdif_runtime_resume(struct device *dev)
dev_err(dev, "spdif_in_clk_enable failed: %d\n", ret); dev_err(dev, "spdif_in_clk_enable failed: %d\n", ret);
return ret; return ret;
} }
}
regcache_cache_only(spdif->regmap, false); regcache_cache_only(spdif->regmap, false);
regcache_sync(spdif->regmap); regcache_sync(spdif->regmap);
return ret; return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
@@ -148,21 +153,25 @@ static int tegra210_spdif_set_dai_sysclk(struct snd_soc_dai *dai,
return -EINVAL; return -EINVAL;
} }
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (dir == SND_SOC_CLOCK_OUT) { if (dir == SND_SOC_CLOCK_OUT) {
ret = clk_set_rate(spdif->clk_spdif_out, spdif_out_clock_rate); ret = clk_set_rate(
spdif->clk_spdif_out, spdif_out_clock_rate);
if (ret) { if (ret) {
dev_err(dev, "Can't set SPDIF Out clock rate: %d\n", dev_err(dev, "Can't set SPDIF Out clock rate: %d\n",
ret); ret);
return ret; return ret;
} }
} else { } else {
ret = clk_set_rate(spdif->clk_spdif_in, spdif_in_clock_rate); ret = clk_set_rate(
spdif->clk_spdif_in, spdif_in_clock_rate);
if (ret) { if (ret) {
dev_err(dev, "Can't set SPDIF In clock rate: %d\n", dev_err(dev, "Can't set SPDIF In clock rate: %d\n",
ret); ret);
return ret; return ret;
} }
} }
}
return 0; return 0;
} }
@@ -176,6 +185,8 @@ static int tegra210_spdif_hw_params(struct snd_pcm_substream *substream,
int channels, audio_bits, bit_mode; int channels, audio_bits, bit_mode;
struct tegra210_xbar_cif_conf cif_conf; struct tegra210_xbar_cif_conf cif_conf;
memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
channels = params_channels(params); channels = params_channels(params);
if (channels < 2) { if (channels < 2) {
@@ -196,7 +207,6 @@ static int tegra210_spdif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
memset(&cif_conf, 0, sizeof(cif_conf));
cif_conf.audio_channels = channels; cif_conf.audio_channels = channels;
cif_conf.client_channels = channels; cif_conf.client_channels = channels;
cif_conf.audio_bits = audio_bits; cif_conf.audio_bits = audio_bits;
@@ -390,7 +400,7 @@ static int tegra210_spdif_platform_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, spdif); dev_set_drvdata(&pdev->dev, spdif);
spdif->soc_data = soc_data; spdif->soc_data = soc_data;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "spdif_out"); spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "spdif_out");
if (IS_ERR(spdif->clk_spdif_out)) { if (IS_ERR(spdif->clk_spdif_out)) {
dev_err(&pdev->dev, "Can't retrieve spdif clock\n"); dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
@@ -404,6 +414,7 @@ static int tegra210_spdif_platform_probe(struct platform_device *pdev)
ret = PTR_ERR(spdif->clk_spdif_in); ret = PTR_ERR(spdif->clk_spdif_in);
goto err_spdif_out_clk_put; goto err_spdif_out_clk_put;
} }
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {
@@ -470,8 +481,10 @@ err_suspend:
err_pm_disable: err_pm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
err_spdif_in_clk_put: err_spdif_in_clk_put:
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
devm_clk_put(&pdev->dev, spdif->clk_spdif_in); devm_clk_put(&pdev->dev, spdif->clk_spdif_in);
err_spdif_out_clk_put: err_spdif_out_clk_put:
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
devm_clk_put(&pdev->dev, spdif->clk_spdif_out); devm_clk_put(&pdev->dev, spdif->clk_spdif_out);
err: err:
return ret; return ret;
@@ -487,8 +500,10 @@ static int tegra210_spdif_platform_remove(struct platform_device *pdev)
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
tegra210_spdif_runtime_suspend(&pdev->dev); tegra210_spdif_runtime_suspend(&pdev->dev);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
devm_clk_put(&pdev->dev, spdif->clk_spdif_out); devm_clk_put(&pdev->dev, spdif->clk_spdif_out);
devm_clk_put(&pdev->dev, spdif->clk_spdif_in); devm_clk_put(&pdev->dev, spdif->clk_spdif_in);
}
return 0; return 0;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_xbar_alt.c - Tegra210 XBAR driver * tegra210_xbar_alt.c - Tegra210 XBAR driver
* *
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2015 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -26,12 +26,18 @@
#include <linux/tegra_pm_domains.h> #include <linux/tegra_pm_domains.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tegra-soc.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <mach/clk.h> #include <mach/clk.h>
#include "tegra210_xbar_alt.h" #include "tegra210_xbar_alt.h"
/* TODO: remove DRV_NAME_T18X after registering properly */
#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
#define DRV_NAME "tegra210-axbar" #define DRV_NAME "tegra210-axbar"
#else
#include <sound/tegra_audio.h>
#define DRV_NAME DRV_NAME_T18X
#endif
static struct tegra210_xbar *xbar; static struct tegra210_xbar *xbar;
@@ -44,8 +50,7 @@ static const struct regmap_config tegra210_xbar_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.max_register = TEGRA210_XBAR_PART2_RX + (TEGRA210_XBAR_RX_STRIDE * .max_register = MAX_REGISTER_ADDR,
(TEGRA210_XBAR_AUDIO_RX_COUNT - 1)),
.volatile_reg = tegra210_xbar_volatile_reg, .volatile_reg = tegra210_xbar_volatile_reg,
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
@@ -54,8 +59,10 @@ static int tegra210_xbar_runtime_suspend(struct device *dev)
{ {
regcache_cache_only(xbar->regmap, true); regcache_cache_only(xbar->regmap, true);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
clk_disable(xbar->clk); clk_disable(xbar->clk);
clk_disable(xbar->clk_ape); clk_disable(xbar->clk_ape);
}
return 0; return 0;
} }
@@ -64,6 +71,7 @@ static int tegra210_xbar_runtime_resume(struct device *dev)
{ {
int ret; int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
ret = clk_enable(xbar->clk_ape); ret = clk_enable(xbar->clk_ape);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
@@ -75,6 +83,7 @@ static int tegra210_xbar_runtime_resume(struct device *dev)
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
return ret; return ret;
} }
}
regcache_cache_only(xbar->regmap, false); regcache_cache_only(xbar->regmap, false);
regcache_sync(xbar->regmap); regcache_sync(xbar->regmap);
@@ -97,13 +106,15 @@ static int tegra210_xbar_suspend(struct device *dev)
} }
#endif #endif
static int tegra210_xbar_codec_probe(struct snd_soc_codec *codec) int tegra210_xbar_codec_probe(struct snd_soc_codec *codec)
{ {
codec->control_data = xbar->regmap; codec->control_data = xbar->regmap;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(tegra210_xbar_codec_probe);
#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
#define DAI(sname) \ #define DAI(sname) \
{ \ { \
.name = #sname, \ .name = #sname, \
@@ -200,6 +211,7 @@ static struct snd_soc_dai_driver tegra210_xbar_dais[] = {
DAI(ADX2-4), DAI(ADX2-4),
DAI(ADX2), DAI(ADX2),
}; };
#endif
static const char * const tegra210_xbar_mux_texts[] = { static const char * const tegra210_xbar_mux_texts[] = {
"None", "None",
@@ -325,7 +337,7 @@ static const int tegra210_xbar_mux_values[] = {
/* index 35..53 above are inputs of PART2 Mux */ /* index 35..53 above are inputs of PART2 Mux */
}; };
static int tegra210_xbar_get_value_enum(struct snd_kcontrol *kcontrol, int tegra210_xbar_get_value_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
@@ -359,8 +371,9 @@ static int tegra210_xbar_get_value_enum(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(tegra210_xbar_get_value_enum);
static int tegra210_xbar_put_value_enum(struct snd_kcontrol *kcontrol, int tegra210_xbar_put_value_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
@@ -422,6 +435,7 @@ static int tegra210_xbar_put_value_enum(struct snd_kcontrol *kcontrol,
return change; return change;
} }
EXPORT_SYMBOL_GPL(tegra210_xbar_put_value_enum);
#define MUX_REG(id) (TEGRA210_XBAR_RX_STRIDE * (id)) #define MUX_REG(id) (TEGRA210_XBAR_RX_STRIDE * (id))
@@ -640,7 +654,6 @@ static const struct snd_soc_dapm_widget tegra210_xbar_widgets[] = {
{ name " Mux", "ADX2-3", "ADX2-3 RX" }, \ { name " Mux", "ADX2-3", "ADX2-3 RX" }, \
{ name " Mux", "ADX2-4", "ADX2-4 RX" }, { name " Mux", "ADX2-4", "ADX2-4 RX" },
#define IN_OUT_ROUTES(name) \ #define IN_OUT_ROUTES(name) \
{ name " RX", NULL, name " Receive" }, \ { name " RX", NULL, name " Receive" }, \
{ name " Transmit", NULL, name " TX" }, { name " Transmit", NULL, name " TX" },
@@ -722,6 +735,7 @@ static const struct snd_soc_dapm_route tegra210_xbar_routes[] = {
IN_OUT_ROUTES("ADX2-4") IN_OUT_ROUTES("ADX2-4")
}; };
#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
static struct snd_soc_codec_driver tegra210_xbar_codec = { static struct snd_soc_codec_driver tegra210_xbar_codec = {
.probe = tegra210_xbar_codec_probe, .probe = tegra210_xbar_codec_probe,
.dapm_widgets = tegra210_xbar_widgets, .dapm_widgets = tegra210_xbar_widgets,
@@ -730,13 +744,14 @@ static struct snd_soc_codec_driver tegra210_xbar_codec = {
.num_dapm_routes = ARRAY_SIZE(tegra210_xbar_routes), .num_dapm_routes = ARRAY_SIZE(tegra210_xbar_routes),
.idle_bias_off = 1, .idle_bias_off = 1,
}; };
#endif
static const struct tegra210_xbar_soc_data soc_data_tegra210 = { static const struct tegra210_xbar_soc_data soc_data_tegra210 = {
.regmap_config = &tegra210_xbar_regmap_config, .regmap_config = &tegra210_xbar_regmap_config,
.mask[0] = 0xf1f03ff, .mask[0] = TEGRA210_XBAR_REG_MASK_0,
.mask[1] = 0x3f30031f, .mask[1] = TEGRA210_XBAR_REG_MASK_1,
.mask[2] = 0xff1cf313, .mask[2] = TEGRA210_XBAR_REG_MASK_2,
.reg_count = 3, .mask[3] = TEGRA210_XBAR_REG_MASK_3,
.reg_count = TEGRA210_XBAR_UPDATE_MAX_REG,
.reg_offset = TEGRA210_XBAR_PART1_RX, .reg_offset = TEGRA210_XBAR_PART1_RX,
}; };
@@ -745,57 +760,72 @@ static const struct of_device_id tegra210_xbar_of_match[] = {
{}, {},
}; };
#define CLK_LIST_MASK_TEGRA30 BIT(0)
#define CLK_LIST_MASK_TEGRA114 BIT(1)
#define CLK_LIST_MASK_TEGRA124 BIT(2)
#define CLK_LIST_MASK_TEGRA30_OR_LATER \
(CLK_LIST_MASK_TEGRA30 | CLK_LIST_MASK_TEGRA114 |\
CLK_LIST_MASK_TEGRA124)
#define CLK_LIST_MASK_TEGRA114_OR_LATER \
(CLK_LIST_MASK_TEGRA114 | CLK_LIST_MASK_TEGRA124)
static const struct { static const struct {
const char *clk_name; const char *clk_name;
} configlink_clocks[] = { } configlink_clocks[] = {
}; };
/* FIXME: base address for T210 */ #if defined(CONFIG_ARCH_TEGRA_21x_SOC)
static struct of_dev_auxdata tegra210_xbar_auxdata[] = { static struct of_dev_auxdata tegra210_xbar_auxdata[] = {
OF_DEV_AUXDATA("nvidia,tegra210-admaif", 0x702d0000, "tegra210-admaif", NULL), OF_DEV_AUXDATA("nvidia,tegra210-admaif", ADMAIF_BASE_ADDR, "tegra210-admaif", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-i2s", 0x702d1000, "tegra210-i2s.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-i2s", I2S1_BASE_ADDR, "tegra210-i2s.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-i2s", 0x702d1100, "tegra210-i2s.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-i2s", I2S2_BASE_ADDR, "tegra210-i2s.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-i2s", 0x702d1200, "tegra210-i2s.2", NULL), OF_DEV_AUXDATA("nvidia,tegra210-i2s", I2S3_BASE_ADDR, "tegra210-i2s.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-i2s", 0x702d1300, "tegra210-i2s.3", NULL), OF_DEV_AUXDATA("nvidia,tegra210-i2s", I2S4_BASE_ADDR, "tegra210-i2s.3", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-i2s", 0x702d1400, "tegra210-i2s.4", NULL), OF_DEV_AUXDATA("nvidia,tegra210-i2s", I2S5_BASE_ADDR, "tegra210-i2s.4", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-amx", 0x702d3000, "tegra210-amx.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-amx", AMX1_BASE_ADDR, "tegra210-amx.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-amx", 0x702d3100, "tegra210-amx.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-amx", AMX2_BASE_ADDR, "tegra210-amx.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-adx", 0x702d3800, "tegra210-adx.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-adx", ADX1_BASE_ADDR, "tegra210-adx.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-adx", 0x702d3900, "tegra210-adx.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-adx", ADX2_BASE_ADDR, "tegra210-adx.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7000, "tegra210-afc.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC1_BASE_ADDR, "tegra210-afc.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7100, "tegra210-afc.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC2_BASE_ADDR, "tegra210-afc.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7200, "tegra210-afc.2", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC3_BASE_ADDR, "tegra210-afc.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7300, "tegra210-afc.3", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC4_BASE_ADDR, "tegra210-afc.3", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7400, "tegra210-afc.4", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC5_BASE_ADDR, "tegra210-afc.4", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-afc", 0x702d7500, "tegra210-afc.5", NULL), OF_DEV_AUXDATA("nvidia,tegra210-afc", AFC6_BASE_ADDR, "tegra210-afc.5", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-sfc", 0x702d2000, "tegra210-sfc.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-sfc", SFC1_BASE_ADDR, "tegra210-sfc.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-sfc", 0x702d2200, "tegra210-sfc.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-sfc", SFC2_BASE_ADDR, "tegra210-sfc.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-sfc", 0x702d2400, "tegra210-sfc.2", NULL), OF_DEV_AUXDATA("nvidia,tegra210-sfc", SFC3_BASE_ADDR, "tegra210-sfc.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-sfc", 0x702d2600, "tegra210-sfc.3", NULL), OF_DEV_AUXDATA("nvidia,tegra210-sfc", SFC4_BASE_ADDR, "tegra210-sfc.3", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-mvc", 0x702da000, "tegra210-mvc.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-mvc", MVC1_BASE_ADDR, "tegra210-mvc.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-mvc", 0x702da200, "tegra210-mvc.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-mvc", MVC2_BASE_ADDR, "tegra210-mvc.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-iqc", 0x702de000, "tegra210-iqc.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-iqc", IQC1_BASE_ADDR, "tegra210-iqc.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-iqc", 0x702de200, "tegra210-iqc.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-iqc", IQC2_BASE_ADDR, "tegra210-iqc.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4000, "tegra210-dmic.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-dmic", DMIC1_BASE_ADDR, "tegra210-dmic.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4100, "tegra210-dmic.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-dmic", DMIC2_BASE_ADDR, "tegra210-dmic.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4200, "tegra210-dmic.2", NULL), OF_DEV_AUXDATA("nvidia,tegra210-dmic", DMIC3_BASE_ADDR, "tegra210-dmic.2", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-ope", 0x702d8000, "tegra210-ope.0", NULL), OF_DEV_AUXDATA("nvidia,tegra210-ope", OPE1_BASE_ADDR, "tegra210-ope.0", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-ope", 0x702d8400, "tegra210-ope.1", NULL), OF_DEV_AUXDATA("nvidia,tegra210-ope", OPE2_BASE_ADDR, "tegra210-ope.1", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-amixer", 0x702dbb00, "tegra210-mixer", NULL), OF_DEV_AUXDATA("nvidia,tegra210-amixer", AMIXER1_BASE_ADDR, "tegra210-mixer", NULL),
OF_DEV_AUXDATA("nvidia,tegra210-spdif", 0x702d6000, "tegra210-spdif", NULL), OF_DEV_AUXDATA("nvidia,tegra210-spdif", SPDIF1_BASE_ADDR, "tegra210-spdif", NULL),
{} {}
}; };
static int tegra210_xbar_registration(struct platform_device *pdev)
{
int ret;
tegra210_xbar_codec.num_dapm_widgets = (NUM_MUX_WIDGETS * 3) +
(NUM_DAIS - NUM_MUX_WIDGETS) * 2;
tegra210_xbar_codec.num_dapm_routes =
(NUM_DAIS - NUM_MUX_WIDGETS) * 2 +
(NUM_MUX_WIDGETS * NUM_MUX_INPUT);
ret = snd_soc_register_codec(&pdev->dev, &tegra210_xbar_codec,
tegra210_xbar_dais, NUM_DAIS);
if (ret != 0) {
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
return -EBUSY;
}
of_platform_populate(pdev->dev.of_node, NULL, tegra210_xbar_auxdata,
&pdev->dev);
return 0;
}
#endif
static int tegra210_xbar_probe(struct platform_device *pdev) static int tegra210_xbar_probe(struct platform_device *pdev)
{ {
struct clk *clk; struct clk *clk;
@@ -841,6 +871,7 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
xbar->soc_data = soc_data; xbar->soc_data = soc_data;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
xbar->clk = devm_clk_get(&pdev->dev, "ahub"); xbar->clk = devm_clk_get(&pdev->dev, "ahub");
if (IS_ERR(xbar->clk)) { if (IS_ERR(xbar->clk)) {
dev_err(&pdev->dev, "Can't retrieve ahub clock\n"); dev_err(&pdev->dev, "Can't retrieve ahub clock\n");
@@ -861,6 +892,7 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
ret = PTR_ERR(xbar->clk_ape); ret = PTR_ERR(xbar->clk_ape);
goto err_clk_put_parent; goto err_clk_put_parent;
} }
}
parent_clk = clk_get_parent(xbar->clk); parent_clk = clk_get_parent(xbar->clk);
if (IS_ERR(parent_clk)) { if (IS_ERR(parent_clk)) {
@@ -869,6 +901,7 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
goto err_clk_put_ape; goto err_clk_put_ape;
} }
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
ret = clk_set_rate(xbar->clk_parent, 24560000); ret = clk_set_rate(xbar->clk_parent, 24560000);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to set clock rate of pll_a_out0\n"); dev_err(&pdev->dev, "Failed to set clock rate of pll_a_out0\n");
@@ -882,11 +915,11 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
} }
ret = clk_set_rate(xbar->clk, 12288000); ret = clk_set_rate(xbar->clk, 12288000);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to set clock rate of ahub\n"); dev_err(&pdev->dev, "Failed to set clock rate of ahub\n");
goto err_clk_put_ape; goto err_clk_put_ape;
} }
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
@@ -922,15 +955,14 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
goto err_pm_disable; goto err_pm_disable;
} }
ret = snd_soc_register_codec(&pdev->dev, &tegra210_xbar_codec, #if defined(CONFIG_ARCH_TEGRA_21x_SOC)
tegra210_xbar_dais, ARRAY_SIZE(tegra210_xbar_dais)); ret = tegra210_xbar_registration(pdev);
if (ret != 0) { #else
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret); ret = tegra186_xbar_registration(pdev);
#endif
if (ret == -EBUSY)
goto err_suspend; goto err_suspend;
}
of_platform_populate(pdev->dev.of_node, NULL, tegra210_xbar_auxdata,
&pdev->dev);
return 0; return 0;
err_suspend: err_suspend:
@@ -944,6 +976,7 @@ err_clk_set_parent:
err_clk_put_ape: err_clk_put_ape:
clk_put(xbar->clk_ape); clk_put(xbar->clk_ape);
err_clk_put_parent: err_clk_put_parent:
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
clk_put(xbar->clk_parent); clk_put(xbar->clk_parent);
err_clk_put: err_clk_put:
devm_clk_put(&pdev->dev, xbar->clk); devm_clk_put(&pdev->dev, xbar->clk);