mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
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:
committed by
Sameer Pujar
parent
529ec76bea
commit
ee8192fe65
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,11 +355,13 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dmic->soc_data = soc_data;
|
dmic->soc_data = soc_data;
|
||||||
|
|
||||||
dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (IS_ERR(dmic->clk_dmic)) {
|
dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL);
|
||||||
dev_err(&pdev->dev, "Can't retrieve dmic clock\n");
|
if (IS_ERR(dmic->clk_dmic)) {
|
||||||
ret = PTR_ERR(dmic->clk_dmic);
|
dev_err(&pdev->dev, "Can't retrieve dmic clock\n");
|
||||||
goto err;
|
ret = PTR_ERR(dmic->clk_dmic);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
@@ -430,7 +429,8 @@ err_suspend:
|
|||||||
err_pm_disable:
|
err_pm_disable:
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
err_clk_put:
|
err_clk_put:
|
||||||
devm_clk_put(&pdev->dev, dmic->clk_dmic);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||||
|
devm_clk_put(&pdev->dev, dmic->clk_dmic);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,40 +69,44 @@ 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 ((val & TEGRA210_I2S_CTRL_MASTER_EN_MASK) ==
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
TEGRA210_I2S_CTRL_MASTER_EN) {
|
if ((val & TEGRA210_I2S_CTRL_MASTER_EN_MASK) ==
|
||||||
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
|
TEGRA210_I2S_CTRL_MASTER_EN) {
|
||||||
if (ret) {
|
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
|
||||||
dev_err(dev, "Can't set parent of I2S clock\n");
|
if (ret) {
|
||||||
return ret;
|
dev_err(dev, "Can't set parent of I2S clock\n");
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
return ret;
|
"Can't set I2S clock rate: %d\n", ret);
|
||||||
}
|
return ret;
|
||||||
} else {
|
}
|
||||||
ret = clk_set_rate(i2s->clk_i2s_sync, clock_rate);
|
} else {
|
||||||
if (ret) {
|
ret = clk_set_rate(i2s->clk_i2s_sync, clock_rate);
|
||||||
dev_err(dev, "Can't set I2S sync clock rate\n");
|
if (ret) {
|
||||||
return ret;
|
dev_err(dev, "Can't set I2S sync clock rate\n");
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_sync);
|
ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_sync);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Can't set parent of i2s clock\n");
|
dev_err(dev, "Can't set parent of i2s clock\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
return ret;
|
"Can't set I2S clock rate: %d\n", 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,21 +224,27 @@ 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 (!IS_ERR(i2s->pin_idle_state)) {
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
ret = pinctrl_select_state(i2s->pinctrl, i2s->pin_idle_state);
|
if (!IS_ERR(i2s->pin_idle_state)) {
|
||||||
if (ret < 0)
|
ret = pinctrl_select_state(
|
||||||
dev_err(dev, "setting dap pinctrl idle state failed\n");
|
i2s->pinctrl, i2s->pin_idle_state);
|
||||||
}
|
if (ret < 0)
|
||||||
|
dev_err(dev, "setting dap pinctrl idle state failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (i2s->num_supplies > 0) {
|
if (i2s->num_supplies > 0) {
|
||||||
ret = regulator_bulk_disable(i2s->num_supplies,
|
ret = regulator_bulk_disable(i2s->num_supplies,
|
||||||
i2s->supplies);
|
i2s->supplies);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(dev, "failed to disable i2s io regulator\n");
|
dev_err(dev, "failed to disable i2s io regulator\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regcache_cache_only(i2s->regmap, true);
|
||||||
|
|
||||||
|
clk_disable_unprepare(i2s->clk_i2s);
|
||||||
|
} else
|
||||||
|
regcache_cache_only(i2s->regmap, true);
|
||||||
|
|
||||||
regcache_cache_only(i2s->regmap, true);
|
|
||||||
clk_disable_unprepare(i2s->clk_i2s);
|
|
||||||
pm_runtime_put_sync(dev->parent);
|
pm_runtime_put_sync(dev->parent);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -251,24 +261,26 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ERR(i2s->pin_default_state)) {
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
ret = pinctrl_select_state(i2s->pinctrl,
|
if (!IS_ERR(i2s->pin_default_state)) {
|
||||||
i2s->pin_default_state);
|
ret = pinctrl_select_state(i2s->pinctrl,
|
||||||
if (ret < 0)
|
i2s->pin_default_state);
|
||||||
dev_err(dev, "setting dap pinctrl default state failed\n");
|
if (ret < 0)
|
||||||
}
|
dev_err(dev, "setting dap pinctrl default state failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (i2s->num_supplies > 0) {
|
if (i2s->num_supplies > 0) {
|
||||||
ret = regulator_bulk_enable(i2s->num_supplies,
|
ret = regulator_bulk_enable(i2s->num_supplies,
|
||||||
i2s->supplies);
|
i2s->supplies);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(dev, "failed to enable i2s io regulator\n");
|
dev_err(dev, "failed to enable i2s io regulator\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clk_prepare_enable(i2s->clk_i2s);
|
ret = clk_prepare_enable(i2s->clk_i2s);
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regcache_cache_only(i2s->regmap, false);
|
regcache_cache_only(i2s->regmap, false);
|
||||||
@@ -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,34 +833,35 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
|
|||||||
i2s->enable_cya = false;
|
i2s->enable_cya = false;
|
||||||
i2s->loopback = 0;
|
i2s->loopback = 0;
|
||||||
|
|
||||||
i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (IS_ERR(i2s->clk_i2s)) {
|
i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
|
||||||
dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
|
if (IS_ERR(i2s->clk_i2s)) {
|
||||||
ret = PTR_ERR(i2s->clk_i2s);
|
dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
|
||||||
goto err;
|
ret = PTR_ERR(i2s->clk_i2s);
|
||||||
}
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
i2s->clk_i2s_sync = devm_clk_get(&pdev->dev, "ext_audio_sync");
|
i2s->clk_i2s_sync = devm_clk_get(&pdev->dev, "ext_audio_sync");
|
||||||
if (IS_ERR(i2s->clk_i2s_sync)) {
|
if (IS_ERR(i2s->clk_i2s_sync)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve i2s_sync clock\n");
|
dev_err(&pdev->dev, "Can't retrieve i2s_sync clock\n");
|
||||||
ret = PTR_ERR(i2s->clk_i2s_sync);
|
ret = PTR_ERR(i2s->clk_i2s_sync);
|
||||||
goto err_clk_put;
|
goto err_clk_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->clk_audio_sync = devm_clk_get(&pdev->dev, "audio_sync");
|
i2s->clk_audio_sync = devm_clk_get(&pdev->dev, "audio_sync");
|
||||||
if (IS_ERR(i2s->clk_audio_sync)) {
|
if (IS_ERR(i2s->clk_audio_sync)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve audio sync clock\n");
|
dev_err(&pdev->dev, "Can't retrieve audio sync clock\n");
|
||||||
ret = PTR_ERR(i2s->clk_audio_sync);
|
ret = PTR_ERR(i2s->clk_audio_sync);
|
||||||
goto err_i2s_sync_clk_put;
|
goto err_i2s_sync_clk_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
|
i2s->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
|
||||||
if (IS_ERR(i2s->clk_pll_a_out0)) {
|
if (IS_ERR(i2s->clk_pll_a_out0)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
|
dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
|
||||||
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,57 +926,60 @@ 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 (of_property_read_string(np, "prod-name", &prod_name) == 0)
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
tegra_pinctrl_config_prod(&pdev->dev, prod_name);
|
if (of_property_read_string(np, "prod-name", &prod_name) == 0)
|
||||||
|
tegra_pinctrl_config_prod(&pdev->dev, prod_name);
|
||||||
|
|
||||||
num_supplies = of_property_count_strings(np, "regulator-supplies");
|
num_supplies =
|
||||||
if (num_supplies > 0) {
|
of_property_count_strings(np, "regulator-supplies");
|
||||||
i2s->num_supplies = num_supplies;
|
if (num_supplies > 0) {
|
||||||
i2s->supplies = devm_kzalloc(&pdev->dev, num_supplies *
|
i2s->num_supplies = num_supplies;
|
||||||
sizeof(*i2s->supplies), GFP_KERNEL);
|
i2s->supplies = devm_kzalloc(&pdev->dev, num_supplies *
|
||||||
if (!i2s->supplies) {
|
sizeof(*i2s->supplies), GFP_KERNEL);
|
||||||
ret = -ENOMEM;
|
if (!i2s->supplies) {
|
||||||
goto err_pll_a_out0_clk_put;
|
ret = -ENOMEM;
|
||||||
|
goto err_pll_a_out0_clk_put;
|
||||||
|
}
|
||||||
|
of_property_for_each_string(np,
|
||||||
|
"regulator-supplies", prop, supply)
|
||||||
|
i2s->supplies[count++].supply = supply;
|
||||||
|
|
||||||
|
ret = devm_regulator_bulk_get(
|
||||||
|
&pdev->dev, i2s->num_supplies,
|
||||||
|
i2s->supplies);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"Failed to get supplies: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
of_property_for_each_string(np, "regulator-supplies",
|
|
||||||
prop, supply)
|
|
||||||
i2s->supplies[count++].supply = supply;
|
|
||||||
|
|
||||||
ret = devm_regulator_bulk_get(&pdev->dev, i2s->num_supplies,
|
i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||||
i2s->supplies);
|
if (IS_ERR(i2s->pinctrl)) {
|
||||||
if (ret) {
|
dev_warn(&pdev->dev, "Missing pinctrl device\n");
|
||||||
dev_err(&pdev->dev,
|
goto err_dap;
|
||||||
"Failed to get supplies: %d\n", ret);
|
}
|
||||||
return ret;
|
|
||||||
|
i2s->pin_default_state = pinctrl_lookup_state(i2s->pinctrl,
|
||||||
|
"dap_active");
|
||||||
|
if (IS_ERR(i2s->pin_default_state)) {
|
||||||
|
dev_warn(&pdev->dev, "Missing dap-active state\n");
|
||||||
|
goto err_dap;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s->pin_idle_state = pinctrl_lookup_state(i2s->pinctrl,
|
||||||
|
"dap_inactive");
|
||||||
|
if (IS_ERR(i2s->pin_idle_state)) {
|
||||||
|
dev_warn(&pdev->dev, "Missing dap-inactive state\n");
|
||||||
|
goto err_dap;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pinctrl_select_state(i2s->pinctrl, i2s->pin_idle_state);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "setting state failed\n");
|
||||||
|
goto err_dap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
||||||
if (IS_ERR(i2s->pinctrl)) {
|
|
||||||
dev_warn(&pdev->dev, "Missing pinctrl device\n");
|
|
||||||
goto err_dap;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2s->pin_default_state = pinctrl_lookup_state(i2s->pinctrl,
|
|
||||||
"dap_active");
|
|
||||||
if (IS_ERR(i2s->pin_default_state)) {
|
|
||||||
dev_warn(&pdev->dev, "Missing dap-active state\n");
|
|
||||||
goto err_dap;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2s->pin_idle_state = pinctrl_lookup_state(i2s->pinctrl,
|
|
||||||
"dap_inactive");
|
|
||||||
if (IS_ERR(i2s->pin_idle_state)) {
|
|
||||||
dev_warn(&pdev->dev, "Missing dap-inactive state\n");
|
|
||||||
goto err_dap;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pinctrl_select_state(i2s->pinctrl, i2s->pin_idle_state);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(&pdev->dev, "setting state failed\n");
|
|
||||||
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,7 +1004,8 @@ 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:
|
||||||
clk_put(i2s->clk_pll_a_out0);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||||
|
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);
|
||||||
err_i2s_sync_clk_put:
|
err_i2s_sync_clk_put:
|
||||||
@@ -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);
|
||||||
|
|
||||||
devm_clk_put(&pdev->dev, i2s->clk_i2s);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
devm_clk_put(&pdev->dev, i2s->clk_audio_sync);
|
devm_clk_put(&pdev->dev, i2s->clk_i2s);
|
||||||
devm_clk_put(&pdev->dev, i2s->clk_i2s_sync);
|
devm_clk_put(&pdev->dev, i2s->clk_audio_sync);
|
||||||
clk_put(i2s->clk_pll_a_out0);
|
devm_clk_put(&pdev->dev, i2s->clk_i2s_sync);
|
||||||
|
clk_put(i2s->clk_pll_a_out0);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,11 +344,13 @@ static int tegra210_iqc_platform_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
iqc->soc_data = soc_data;
|
iqc->soc_data = soc_data;
|
||||||
|
|
||||||
iqc->clk_iqc = devm_clk_get(&pdev->dev, NULL);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (IS_ERR(iqc->clk_iqc)) {
|
iqc->clk_iqc = devm_clk_get(&pdev->dev, NULL);
|
||||||
dev_err(&pdev->dev, "Can't retrieve iqc clock\n");
|
if (IS_ERR(iqc->clk_iqc)) {
|
||||||
ret = PTR_ERR(iqc->clk_iqc);
|
dev_err(&pdev->dev, "Can't retrieve iqc clock\n");
|
||||||
goto err;
|
ret = PTR_ERR(iqc->clk_iqc);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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_in);
|
||||||
|
}
|
||||||
|
|
||||||
clk_disable_unprepare(spdif->clk_spdif_out);
|
|
||||||
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,22 +82,24 @@ static int tegra210_spdif_runtime_resume(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clk_prepare_enable(spdif->clk_spdif_out);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (ret) {
|
ret = clk_prepare_enable(spdif->clk_spdif_out);
|
||||||
dev_err(dev, "spdif_out_clk_enable failed: %d\n", ret);
|
if (ret) {
|
||||||
return ret;
|
dev_err(dev, "spdif_out_clk_enable failed: %d\n", ret);
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = clk_prepare_enable(spdif->clk_spdif_in);
|
ret = clk_prepare_enable(spdif->clk_spdif_in);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
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,19 +153,23 @@ static int tegra210_spdif_set_dai_sysclk(struct snd_soc_dai *dai,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir == SND_SOC_CLOCK_OUT) {
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
ret = clk_set_rate(spdif->clk_spdif_out, spdif_out_clock_rate);
|
if (dir == SND_SOC_CLOCK_OUT) {
|
||||||
if (ret) {
|
ret = clk_set_rate(
|
||||||
dev_err(dev, "Can't set SPDIF Out clock rate: %d\n",
|
spdif->clk_spdif_out, spdif_out_clock_rate);
|
||||||
ret);
|
if (ret) {
|
||||||
return ret;
|
dev_err(dev, "Can't set SPDIF Out clock rate: %d\n",
|
||||||
}
|
ret);
|
||||||
} else {
|
return ret;
|
||||||
ret = clk_set_rate(spdif->clk_spdif_in, spdif_in_clock_rate);
|
}
|
||||||
if (ret) {
|
} else {
|
||||||
dev_err(dev, "Can't set SPDIF In clock rate: %d\n",
|
ret = clk_set_rate(
|
||||||
ret);
|
spdif->clk_spdif_in, spdif_in_clock_rate);
|
||||||
return ret;
|
if (ret) {
|
||||||
|
dev_err(dev, "Can't set SPDIF In clock rate: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,19 +400,20 @@ 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");
|
||||||
|
if (IS_ERR(spdif->clk_spdif_out)) {
|
||||||
|
dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
|
||||||
|
ret = PTR_ERR(spdif->clk_spdif_out);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
spdif->clk_spdif_out = devm_clk_get(&pdev->dev, "spdif_out");
|
spdif->clk_spdif_in = devm_clk_get(&pdev->dev, "spdif_in");
|
||||||
if (IS_ERR(spdif->clk_spdif_out)) {
|
if (IS_ERR(spdif->clk_spdif_in)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
|
dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
|
||||||
ret = PTR_ERR(spdif->clk_spdif_out);
|
ret = PTR_ERR(spdif->clk_spdif_in);
|
||||||
goto err;
|
goto err_spdif_out_clk_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
spdif->clk_spdif_in = devm_clk_get(&pdev->dev, "spdif_in");
|
|
||||||
if (IS_ERR(spdif->clk_spdif_in)) {
|
|
||||||
dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
|
|
||||||
ret = PTR_ERR(spdif->clk_spdif_in);
|
|
||||||
goto err_spdif_out_clk_put;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
@@ -470,9 +481,11 @@ 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:
|
||||||
devm_clk_put(&pdev->dev, spdif->clk_spdif_in);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||||
|
devm_clk_put(&pdev->dev, spdif->clk_spdif_in);
|
||||||
err_spdif_out_clk_put:
|
err_spdif_out_clk_put:
|
||||||
devm_clk_put(&pdev->dev, spdif->clk_spdif_out);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||||
|
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);
|
||||||
|
|
||||||
devm_clk_put(&pdev->dev, spdif->clk_spdif_out);
|
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_out);
|
||||||
|
devm_clk_put(&pdev->dev, spdif->clk_spdif_in);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
clk_disable(xbar->clk);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
clk_disable(xbar->clk_ape);
|
clk_disable(xbar->clk);
|
||||||
|
clk_disable(xbar->clk_ape);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -64,16 +71,18 @@ static int tegra210_xbar_runtime_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = clk_enable(xbar->clk_ape);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (ret) {
|
ret = clk_enable(xbar->clk_ape);
|
||||||
dev_err(dev, "clk_enable failed: %d\n", ret);
|
if (ret) {
|
||||||
return ret;
|
dev_err(dev, "clk_enable failed: %d\n", ret);
|
||||||
}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = clk_enable(xbar->clk);
|
ret = clk_enable(xbar->clk);
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regcache_cache_only(xbar->regmap, false);
|
regcache_cache_only(xbar->regmap, false);
|
||||||
@@ -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,25 +871,27 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
xbar->soc_data = soc_data;
|
xbar->soc_data = soc_data;
|
||||||
|
|
||||||
xbar->clk = devm_clk_get(&pdev->dev, "ahub");
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (IS_ERR(xbar->clk)) {
|
xbar->clk = devm_clk_get(&pdev->dev, "ahub");
|
||||||
dev_err(&pdev->dev, "Can't retrieve ahub clock\n");
|
if (IS_ERR(xbar->clk)) {
|
||||||
ret = PTR_ERR(xbar->clk);
|
dev_err(&pdev->dev, "Can't retrieve ahub clock\n");
|
||||||
goto err;
|
ret = PTR_ERR(xbar->clk);
|
||||||
}
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
xbar->clk_parent = clk_get_sys(NULL, "pll_a_out0");
|
xbar->clk_parent = clk_get_sys(NULL, "pll_a_out0");
|
||||||
if (IS_ERR(xbar->clk)) {
|
if (IS_ERR(xbar->clk)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
|
dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
|
||||||
ret = PTR_ERR(xbar->clk_parent);
|
ret = PTR_ERR(xbar->clk_parent);
|
||||||
goto err_clk_put;
|
goto err_clk_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
xbar->clk_ape = clk_get_sys(NULL, "xbar.ape");
|
xbar->clk_ape = clk_get_sys(NULL, "xbar.ape");
|
||||||
if (IS_ERR(xbar->clk_ape)) {
|
if (IS_ERR(xbar->clk_ape)) {
|
||||||
dev_err(&pdev->dev, "Can't retrieve ape clock\n");
|
dev_err(&pdev->dev, "Can't retrieve ape clock\n");
|
||||||
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);
|
||||||
@@ -869,23 +901,24 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
|
|||||||
goto err_clk_put_ape;
|
goto err_clk_put_ape;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clk_set_rate(xbar->clk_parent, 24560000);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||||
if (ret) {
|
ret = clk_set_rate(xbar->clk_parent, 24560000);
|
||||||
dev_err(&pdev->dev, "Failed to set clock rate of pll_a_out0\n");
|
if (ret) {
|
||||||
goto err_clk_put_ape;
|
dev_err(&pdev->dev, "Failed to set clock rate of pll_a_out0\n");
|
||||||
}
|
goto err_clk_put_ape;
|
||||||
|
}
|
||||||
|
|
||||||
ret = clk_set_parent(xbar->clk, xbar->clk_parent);
|
ret = clk_set_parent(xbar->clk, xbar->clk_parent);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to set parent clock with pll_a_out0\n");
|
dev_err(&pdev->dev, "Failed to set parent clock with pll_a_out0\n");
|
||||||
goto err_clk_put_ape;
|
goto err_clk_put_ape;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -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,7 +976,8 @@ 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:
|
||||||
clk_put(xbar->clk_parent);
|
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||||
|
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);
|
||||||
err:
|
err:
|
||||||
|
|||||||
Reference in New Issue
Block a user