mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ASoC: Tegra-alt: Add tegra210 OPE driver
Add tegra210 ope, peq and mbdrc driver. Change-Id: I2fa00b053343d7e2824a0001c3d41420462fe8d7 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/439630 GVS: Gerrit_Virtual_Submit Reviewed-by: Songhee Baek <sbaek@nvidia.com> Reviewed-by: Arun Shamanna Lakshmi <aruns@nvidia.com> Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
6f662309f7
commit
0b7e079a9d
@@ -148,6 +148,12 @@ config SND_SOC_TEGRA210_SPDIF_ALT
|
|||||||
help
|
help
|
||||||
Say Y or M if you want to add support for Tegra210 SPDIF module.
|
Say Y or M if you want to add support for Tegra210 SPDIF module.
|
||||||
|
|
||||||
|
config SND_SOC_TEGRA210_OPE_ALT
|
||||||
|
tristate "Tegra210 OPE driver"
|
||||||
|
depends on SND_SOC_TEGRA_ALT && SND_SOC_TEGRA_ALT_210
|
||||||
|
help
|
||||||
|
Say Y or M if you want to add support for Tegra210 OPE module.
|
||||||
|
|
||||||
config SND_SOC_TEGRA210_ADSP_ALT
|
config SND_SOC_TEGRA210_ADSP_ALT
|
||||||
tristate "Tegra210 ADSP driver"
|
tristate "Tegra210 ADSP driver"
|
||||||
depends on SND_SOC_TEGRA_ALT && SND_SOC_TEGRA_ALT_210 && TEGRA_NVADSP
|
depends on SND_SOC_TEGRA_ALT && SND_SOC_TEGRA_ALT_210 && TEGRA_NVADSP
|
||||||
@@ -199,6 +205,7 @@ config SND_SOC_TEGRA_GRENADA_ALT
|
|||||||
select SND_SOC_TEGRA210_SFC_ALT
|
select SND_SOC_TEGRA210_SFC_ALT
|
||||||
select SND_SOC_TEGRA210_AFC_ALT
|
select SND_SOC_TEGRA210_AFC_ALT
|
||||||
select SND_SOC_TEGRA210_MVC_ALT
|
select SND_SOC_TEGRA210_MVC_ALT
|
||||||
|
select SND_SOC_TEGRA210_OPE_ALT
|
||||||
select SND_SOC_TEGRA210_IQC_ALT
|
select SND_SOC_TEGRA210_IQC_ALT
|
||||||
select SND_SOC_TEGRA210_SPDIF_ALT
|
select SND_SOC_TEGRA210_SPDIF_ALT
|
||||||
select SND_SOC_TEGRA210_ADSP_ALT
|
select SND_SOC_TEGRA210_ADSP_ALT
|
||||||
@@ -222,6 +229,7 @@ config SND_SOC_TEGRA_T210REF_MOBILE_ALT
|
|||||||
select SND_SOC_TEGRA210_SFC_ALT
|
select SND_SOC_TEGRA210_SFC_ALT
|
||||||
select SND_SOC_TEGRA210_AFC_ALT
|
select SND_SOC_TEGRA210_AFC_ALT
|
||||||
select SND_SOC_TEGRA210_MVC_ALT
|
select SND_SOC_TEGRA210_MVC_ALT
|
||||||
|
select SND_SOC_TEGRA210_OPE_ALT
|
||||||
select SND_SOC_TEGRA210_SPDIF_ALT
|
select SND_SOC_TEGRA210_SPDIF_ALT
|
||||||
select SND_SOC_TEGRA210_ADSP_ALT
|
select SND_SOC_TEGRA210_ADSP_ALT
|
||||||
select SND_SOC_SPDIF
|
select SND_SOC_SPDIF
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ snd-soc-tegra210-alt-afc-objs := tegra210_afc_alt.o
|
|||||||
snd-soc-tegra210-alt-mvc-objs := tegra210_mvc_alt.o
|
snd-soc-tegra210-alt-mvc-objs := tegra210_mvc_alt.o
|
||||||
snd-soc-tegra210-alt-iqc-objs := tegra210_iqc_alt.o
|
snd-soc-tegra210-alt-iqc-objs := tegra210_iqc_alt.o
|
||||||
snd-soc-tegra210-alt-spdif-objs := tegra210_spdif_alt.o
|
snd-soc-tegra210-alt-spdif-objs := tegra210_spdif_alt.o
|
||||||
|
snd-soc-tegra210-alt-ope-objs := tegra210_ope_alt.o
|
||||||
|
snd-soc-tegra210-alt-peq-objs := tegra210_peq_alt.o
|
||||||
|
snd-soc-tegra210-alt-mbdrc-objs := tegra210_mbdrc_alt.o
|
||||||
snd-soc-tegra210-alt-adsp-objs := tegra210_adsp_alt.o
|
snd-soc-tegra210-alt-adsp-objs := tegra210_adsp_alt.o
|
||||||
snd-soc-tegra210-alt-fpga-clock-objs := ahub_unit_fpga_clock.o
|
snd-soc-tegra210-alt-fpga-clock-objs := ahub_unit_fpga_clock.o
|
||||||
|
|
||||||
@@ -53,6 +56,9 @@ obj-$(CONFIG_SND_SOC_TEGRA210_AFC_ALT) += snd-soc-tegra210-alt-afc.o
|
|||||||
obj-$(CONFIG_SND_SOC_TEGRA210_MVC_ALT) += snd-soc-tegra210-alt-mvc.o
|
obj-$(CONFIG_SND_SOC_TEGRA210_MVC_ALT) += snd-soc-tegra210-alt-mvc.o
|
||||||
obj-$(CONFIG_SND_SOC_TEGRA210_IQC_ALT) += snd-soc-tegra210-alt-iqc.o
|
obj-$(CONFIG_SND_SOC_TEGRA210_IQC_ALT) += snd-soc-tegra210-alt-iqc.o
|
||||||
obj-$(CONFIG_SND_SOC_TEGRA210_SPDIF_ALT) += snd-soc-tegra210-alt-spdif.o
|
obj-$(CONFIG_SND_SOC_TEGRA210_SPDIF_ALT) += snd-soc-tegra210-alt-spdif.o
|
||||||
|
obj-$(CONFIG_SND_SOC_TEGRA210_OPE_ALT) += snd-soc-tegra210-alt-ope.o
|
||||||
|
obj-$(CONFIG_SND_SOC_TEGRA210_OPE_ALT) += snd-soc-tegra210-alt-peq.o
|
||||||
|
obj-$(CONFIG_SND_SOC_TEGRA210_OPE_ALT) += snd-soc-tegra210-alt-mbdrc.o
|
||||||
obj-$(CONFIG_SND_SOC_TEGRA210_ADSP_ALT) += snd-soc-tegra210-alt-adsp.o
|
obj-$(CONFIG_SND_SOC_TEGRA210_ADSP_ALT) += snd-soc-tegra210-alt-adsp.o
|
||||||
|
|
||||||
# Tegra machine Support
|
# Tegra machine Support
|
||||||
|
|||||||
787
sound/soc/tegra-alt/tegra210_mbdrc_alt.c
Normal file
787
sound/soc/tegra-alt/tegra210_mbdrc_alt.c
Normal file
@@ -0,0 +1,787 @@
|
|||||||
|
/*
|
||||||
|
* tegra210_mbdrc_alt.c - Tegra210 MBDRC driver
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <sound/core.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
|
||||||
|
#include "tegra210_xbar_alt.h"
|
||||||
|
#include "tegra210_ope_alt.h"
|
||||||
|
#include "tegra210_mbdrc_alt.h"
|
||||||
|
|
||||||
|
/* Default MBDRC parameters */
|
||||||
|
static const struct tegra210_mbdrc_config mbdrc_init_config = {
|
||||||
|
.mode = 0, /* bypass */
|
||||||
|
.rms_off = 48,
|
||||||
|
.peak_rms_mode = 1, /* PEAK */
|
||||||
|
.fliter_structure = 0, /* All-pass tree */
|
||||||
|
.shift_ctrl = 30,
|
||||||
|
.frame_size = 32,
|
||||||
|
.channel_mask = 0x3,
|
||||||
|
.fa_factor = 2048,
|
||||||
|
.fr_factor = 14747,
|
||||||
|
.band_params[MBDRC_LOW_BAND] = {
|
||||||
|
.band = MBDRC_LOW_BAND,
|
||||||
|
.iir_stages = 5,
|
||||||
|
.in_attack_tc = 1044928780,
|
||||||
|
.in_release_tc = 138497695,
|
||||||
|
.fast_attack_tc = 2147483647,
|
||||||
|
.in_threshold = {130, 80, 20, 6},
|
||||||
|
.out_threshold = {155, 55, 13, 6},
|
||||||
|
.ratio = {40960, 8192, 2867, 2048, 410},
|
||||||
|
.makeup_gain = 4,
|
||||||
|
.gain_init = 419430,
|
||||||
|
.gain_attack_tc = 14268942,
|
||||||
|
.gain_release_tc = 1440547090,
|
||||||
|
.fast_release_tc = 2147480170,
|
||||||
|
.biquad_params = {
|
||||||
|
/* Gains : b0, b1, a0, a1, a2 */
|
||||||
|
961046798, -2030431983, 1073741824, 2030431983, -961046798, /* band-0 */
|
||||||
|
1030244425, -2099481453, 1073741824, 2099481453, -1030244425, /* band-1 */
|
||||||
|
1067169294, -2136327263, 1073741824, 2136327263, -1067169294, /* band-2 */
|
||||||
|
434951949, -1306567134, 1073741824, 1306567134, -434951949, /* band-3 */
|
||||||
|
780656019, -1605955641, 1073741824, 1605955641, -780656019, /* band-4 */
|
||||||
|
1024497031, -1817128152, 1073741824, 1817128152, -1024497031, /* band-5 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-6 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-7 */
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.band_params[MBDRC_MID_BAND] = {
|
||||||
|
.band = MBDRC_MID_BAND,
|
||||||
|
.iir_stages = 5,
|
||||||
|
.in_attack_tc = 1581413104,
|
||||||
|
.in_release_tc = 35494783,
|
||||||
|
.fast_attack_tc = 2147483647,
|
||||||
|
.in_threshold = {130, 50, 30, 6},
|
||||||
|
.out_threshold = {106, 50, 30, 13},
|
||||||
|
.ratio = {40960, 2867, 4096, 2867, 410},
|
||||||
|
.makeup_gain = 6,
|
||||||
|
.gain_init = 419430,
|
||||||
|
.gain_attack_tc = 4766887,
|
||||||
|
.gain_release_tc = 1044928780,
|
||||||
|
.fast_release_tc = 2147480170,
|
||||||
|
.biquad_params = {
|
||||||
|
/* Gains : b0, b1, a0, a1, a2 */
|
||||||
|
-1005668963, 1073741824, 0, 1005668963, 0, /* band-0 */
|
||||||
|
998437058, -2067742187, 1073741824, 2067742187, -998437058, /* band-1 */
|
||||||
|
1051963422, -2121153948, 1073741824, 2121153948, -1051963422, /* band-2 */
|
||||||
|
434951949, -1306567134, 1073741824, 1306567134, -434951949, /* band-3 */
|
||||||
|
780656019, -1605955641, 1073741824, 1605955641, -780656019, /* band-4 */
|
||||||
|
1024497031, -1817128152, 1073741824, 1817128152, -1024497031, /* band-5 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-6 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-7 */
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.band_params[MBDRC_HIGH_BAND] = {
|
||||||
|
.band = MBDRC_HIGH_BAND,
|
||||||
|
.iir_stages = 5,
|
||||||
|
.in_attack_tc = 2144750688,
|
||||||
|
.in_release_tc = 70402888,
|
||||||
|
.fast_attack_tc = 2147483647,
|
||||||
|
.in_threshold = {130, 50, 30, 6},
|
||||||
|
.out_threshold = {106, 50, 30, 13},
|
||||||
|
.ratio = {40960, 2867, 4096, 2867, 410},
|
||||||
|
.makeup_gain = 6,
|
||||||
|
.gain_init = 419430,
|
||||||
|
.gain_attack_tc = 4766887,
|
||||||
|
.gain_release_tc = 1044928780,
|
||||||
|
.fast_release_tc = 2147480170,
|
||||||
|
.biquad_params = {
|
||||||
|
/* Gains : b0, b1, a0, a1, a2 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-0 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-1 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-2 */
|
||||||
|
-619925131, 1073741824, 0, 619925131, 0, /* band-3 */
|
||||||
|
606839335, -1455425976, 1073741824, 1455425976, -606839335, /* band-4 */
|
||||||
|
917759617, -1724690840, 1073741824, 1724690840, -917759617, /* band-5 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-6 */
|
||||||
|
1073741824, 0, 0, 0, 0, /* band-7 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
regmap_read(ope->mbdrc_regmap, mc->reg, &val);
|
||||||
|
ucontrol->value.integer.value[0] = (val >> mc->shift) & mask;
|
||||||
|
if (mc->invert)
|
||||||
|
ucontrol->value.integer.value[0] =
|
||||||
|
mc->max - ucontrol->value.integer.value[0];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
val = (ucontrol->value.integer.value[0] & mask);
|
||||||
|
if (mc->invert)
|
||||||
|
val = mc->max - val;
|
||||||
|
val = val << mc->shift;
|
||||||
|
|
||||||
|
return regmap_update_bits(ope->mbdrc_regmap, mc->reg,
|
||||||
|
(mask << mc->shift), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra210_mbdrc_get_enum(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
regmap_read(ope->mbdrc_regmap, e->reg, &val);
|
||||||
|
ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra210_mbdrc_put_enum(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||||
|
unsigned int val;
|
||||||
|
unsigned int mask;
|
||||||
|
|
||||||
|
if (ucontrol->value.enumerated.item[0] > e->max - 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
val = ucontrol->value.enumerated.item[0] << e->shift_l;
|
||||||
|
mask = e->mask << e->shift_l;
|
||||||
|
|
||||||
|
return regmap_update_bits(ope->mbdrc_regmap, e->reg, mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_band_params_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
u32 regs = params->soc.base;
|
||||||
|
u32 mask = params->soc.mask;
|
||||||
|
u32 shift = params->shift;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < params->soc.num_regs; i++, regs += codec->val_bytes) {
|
||||||
|
regmap_read(ope->mbdrc_regmap, regs, &data[i]);
|
||||||
|
data[i] = ((data[i] & mask) >> shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_band_params_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
u32 regs = params->soc.base;
|
||||||
|
u32 mask = params->soc.mask;
|
||||||
|
u32 shift = params->shift;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < params->soc.num_regs; i++, regs += codec->val_bytes)
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, regs, mask,
|
||||||
|
data[i] << shift);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_threshold_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
u32 regs = params->soc.base;
|
||||||
|
u32 num_regs = params->soc.num_regs;
|
||||||
|
u32 val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_regs; i += 4, regs += codec->val_bytes) {
|
||||||
|
regmap_read(ope->mbdrc_regmap, regs, &val);
|
||||||
|
|
||||||
|
data[i] = (val & TEGRA210_MBDRC_THRESH_1ST_MASK) >>
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_SHIFT;
|
||||||
|
data[i + 1] = (val & TEGRA210_MBDRC_THRESH_2ND_MASK) >>
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_SHIFT;
|
||||||
|
data[i + 2] = (val & TEGRA210_MBDRC_THRESH_3RD_MASK) >>
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_SHIFT;
|
||||||
|
data[i + 3] = (val & TEGRA210_MBDRC_THRESH_4TH_MASK) >>
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_threshold_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
u32 regs = params->soc.base;
|
||||||
|
u32 num_regs = params->soc.num_regs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_regs; i += 4, regs += codec->val_bytes) {
|
||||||
|
data[i] = (((data[i] >> TEGRA210_MBDRC_THRESH_1ST_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_MASK) |
|
||||||
|
((data[i + 1] >> TEGRA210_MBDRC_THRESH_2ND_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_MASK) |
|
||||||
|
((data[i + 2] >> TEGRA210_MBDRC_THRESH_3RD_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_MASK) |
|
||||||
|
((data[i + 3] >> TEGRA210_MBDRC_THRESH_4TH_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_MASK));
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, regs,
|
||||||
|
0xffffffff, data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_biquad_coeffs_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
|
||||||
|
memset(data, 0, params->soc.num_regs * codec->val_bytes);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_mbdrc_biquad_coeffs_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 reg_ctrl = params->soc.base;
|
||||||
|
u32 reg_data = reg_ctrl + codec->val_bytes;
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
|
||||||
|
tegra210_xbar_write_ahubram(ope->mbdrc_regmap, reg_ctrl, reg_data,
|
||||||
|
params->shift, data, params->soc.num_regs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * const tegra210_mbdrc_mode_text[] = {
|
||||||
|
"bypass", "fullband", "dualband", "multiband"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct soc_enum tegra210_mbdrc_mode_enum =
|
||||||
|
SOC_ENUM_SINGLE(TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_MBDRC_MODE_SHIFT, 4,
|
||||||
|
tegra210_mbdrc_mode_text);
|
||||||
|
|
||||||
|
static const char * const tegra210_mbdrc_peak_rms_text[] = {
|
||||||
|
"peak", "rms"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct soc_enum tegra210_mbdrc_peak_rms_enum =
|
||||||
|
SOC_ENUM_SINGLE(TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_PEAK_RMS_SHIFT, 2,
|
||||||
|
tegra210_mbdrc_peak_rms_text);
|
||||||
|
|
||||||
|
static const char * const tegra210_mbdrc_filter_structure_text[] = {
|
||||||
|
"all-pass-tree", "flexible"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct soc_enum tegra210_mbdrc_filter_structure_enum =
|
||||||
|
SOC_ENUM_SINGLE(TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_FILTER_STRUCTURE_SHIFT, 2,
|
||||||
|
tegra210_mbdrc_filter_structure_text);
|
||||||
|
|
||||||
|
static const char * const tegra210_mbdrc_frame_size_text[] = {
|
||||||
|
"N1", "N2", "N4", "N8", "N16", "N32", "N64"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct soc_enum tegra210_mbdrc_frame_size_enum =
|
||||||
|
SOC_ENUM_SINGLE(TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_FRAME_SIZE_SHIFT, 7,
|
||||||
|
tegra210_mbdrc_frame_size_text);
|
||||||
|
|
||||||
|
#define TEGRA_MBDRC_BYTES_EXT(xname, xbase, xregs, xshift, xmask) \
|
||||||
|
TEGRA_SOC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, \
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put)
|
||||||
|
|
||||||
|
#define TEGRA_MBDRC_BAND_BYTES_EXT(xname, xbase, xshift, xmask) \
|
||||||
|
TEGRA_MBDRC_BYTES_EXT(xname, xbase, TEGRA210_MBDRC_FILTER_COUNT, \
|
||||||
|
xshift, xmask)
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = {
|
||||||
|
SOC_ENUM_EXT("mbdrc peak-rms mode", tegra210_mbdrc_peak_rms_enum,
|
||||||
|
tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),
|
||||||
|
SOC_ENUM_EXT("mbdrc filter structure",
|
||||||
|
tegra210_mbdrc_filter_structure_enum,
|
||||||
|
tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),
|
||||||
|
SOC_ENUM_EXT("mbdrc frame size", tegra210_mbdrc_frame_size_enum,
|
||||||
|
tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),
|
||||||
|
SOC_ENUM_EXT("mbdrc mode", tegra210_mbdrc_mode_enum,
|
||||||
|
tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum),
|
||||||
|
|
||||||
|
SOC_SINGLE_EXT("mbdrc rms offset", TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_RMS_OFFSET_SHIFT, 0x1ff, 0,
|
||||||
|
tegra210_mbdrc_get, tegra210_mbdrc_put),
|
||||||
|
SOC_SINGLE_EXT("mbdrc shift control", TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_SHIFT_CTRL_SHIFT, 0x1f, 0,
|
||||||
|
tegra210_mbdrc_get, tegra210_mbdrc_put),
|
||||||
|
SOC_SINGLE_EXT("mbdrc master volume", TEGRA210_MBDRC_MASTER_VOLUME,
|
||||||
|
TEGRA210_MBDRC_MASTER_VOLUME_SHIFT, 0xffffffff, 0,
|
||||||
|
tegra210_mbdrc_get, tegra210_mbdrc_put),
|
||||||
|
SOC_SINGLE_EXT("mbdrc fast attack factor", TEGRA210_MBDRC_FAST_FACTOR,
|
||||||
|
TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT, 0xffff, 0,
|
||||||
|
tegra210_mbdrc_get, tegra210_mbdrc_put),
|
||||||
|
SOC_SINGLE_EXT("mbdrc fast release factor", TEGRA210_MBDRC_FAST_FACTOR,
|
||||||
|
TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT, 0xffff, 0,
|
||||||
|
tegra210_mbdrc_get, tegra210_mbdrc_put),
|
||||||
|
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc iir stages", TEGRA210_MBDRC_IIR_CONFIG,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_IIR_CONFIG_NUM_STAGES_SHIFT,
|
||||||
|
TEGRA210_MBDRC_IIR_CONFIG_NUM_STAGES_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc in attack tc", TEGRA210_MBDRC_IN_ATTACK,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT,
|
||||||
|
TEGRA210_MBDRC_IN_ATTACK_TC_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc in release tc", TEGRA210_MBDRC_IN_RELEASE,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT,
|
||||||
|
TEGRA210_MBDRC_IN_RELEASE_TC_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc fast attack tc", TEGRA210_MBDRC_FAST_ATTACK,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT,
|
||||||
|
TEGRA210_MBDRC_FAST_ATTACK_TC_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc in threshold", TEGRA210_MBDRC_IN_THRESHOLD,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff,
|
||||||
|
tegra210_mbdrc_threshold_get, tegra210_mbdrc_threshold_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc out threshold", TEGRA210_MBDRC_OUT_THRESHOLD,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff,
|
||||||
|
tegra210_mbdrc_threshold_get, tegra210_mbdrc_threshold_put),
|
||||||
|
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc ratio", TEGRA210_MBDRC_RATIO_1ST,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT * 5,
|
||||||
|
TEGRA210_MBDRC_RATIO_1ST_SHIFT, TEGRA210_MBDRC_RATIO_1ST_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc makeup gain", TEGRA210_MBDRC_MAKEUP_GAIN,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT,
|
||||||
|
TEGRA210_MBDRC_MAKEUP_GAIN_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc init gain", TEGRA210_MBDRC_INIT_GAIN,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_INIT_GAIN_SHIFT,
|
||||||
|
TEGRA210_MBDRC_INIT_GAIN_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc attack gain", TEGRA210_MBDRC_GAIN_ATTACK,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_GAIN_ATTACK_SHIFT,
|
||||||
|
TEGRA210_MBDRC_GAIN_ATTACK_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc release gain", TEGRA210_MBDRC_GAIN_RELEASE,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_GAIN_RELEASE_SHIFT,
|
||||||
|
TEGRA210_MBDRC_GAIN_RELEASE_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc fast release gain",
|
||||||
|
TEGRA210_MBDRC_FAST_RELEASE,
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT,
|
||||||
|
TEGRA210_MBDRC_FAST_RELEASE_SHIFT,
|
||||||
|
TEGRA210_MBDRC_FAST_RELEASE_MASK,
|
||||||
|
tegra210_mbdrc_band_params_get, tegra210_mbdrc_band_params_put),
|
||||||
|
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc low band biquad coeffs",
|
||||||
|
TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL,
|
||||||
|
TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_get,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc mid band biquad coeffs",
|
||||||
|
TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL +
|
||||||
|
TEGRA210_MBDRC_FILTER_PARAM_STRIDE,
|
||||||
|
TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_get,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_put),
|
||||||
|
TEGRA_SOC_BYTES_EXT("mbdrc high band biquad coeffs",
|
||||||
|
TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL +
|
||||||
|
(TEGRA210_MBDRC_FILTER_PARAM_STRIDE * 2),
|
||||||
|
TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_get,
|
||||||
|
tegra210_mbdrc_biquad_coeffs_put),
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool tegra210_mbdrc_wr_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
if (reg >= TEGRA210_MBDRC_IIR_CONFIG)
|
||||||
|
reg -= ((reg - TEGRA210_MBDRC_IIR_CONFIG) %
|
||||||
|
(TEGRA210_MBDRC_FILTER_PARAM_STRIDE *
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT));
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_MBDRC_CG:
|
||||||
|
case TEGRA210_MBDRC_SOFT_RESET:
|
||||||
|
case TEGRA210_MBDRC_CONFIG:
|
||||||
|
case TEGRA210_MBDRC_CHANNEL_MASK:
|
||||||
|
case TEGRA210_MBDRC_MASTER_VOLUME:
|
||||||
|
case TEGRA210_MBDRC_FAST_FACTOR:
|
||||||
|
case TEGRA210_MBDRC_IIR_CONFIG:
|
||||||
|
case TEGRA210_MBDRC_IN_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_IN_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_FAST_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_IN_THRESHOLD:
|
||||||
|
case TEGRA210_MBDRC_OUT_THRESHOLD:
|
||||||
|
case TEGRA210_MBDRC_RATIO_1ST:
|
||||||
|
case TEGRA210_MBDRC_RATIO_2ND:
|
||||||
|
case TEGRA210_MBDRC_RATIO_3RD:
|
||||||
|
case TEGRA210_MBDRC_RATIO_4TH:
|
||||||
|
case TEGRA210_MBDRC_RATIO_5TH:
|
||||||
|
case TEGRA210_MBDRC_MAKEUP_GAIN:
|
||||||
|
case TEGRA210_MBDRC_INIT_GAIN:
|
||||||
|
case TEGRA210_MBDRC_GAIN_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_GAIN_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_FAST_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_mbdrc_rd_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
if (reg >= TEGRA210_MBDRC_IIR_CONFIG)
|
||||||
|
reg -= ((reg - TEGRA210_MBDRC_IIR_CONFIG) %
|
||||||
|
(TEGRA210_MBDRC_FILTER_PARAM_STRIDE *
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT));
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_MBDRC_CG:
|
||||||
|
case TEGRA210_MBDRC_SOFT_RESET:
|
||||||
|
case TEGRA210_MBDRC_STATUS:
|
||||||
|
case TEGRA210_MBDRC_CONFIG:
|
||||||
|
case TEGRA210_MBDRC_CHANNEL_MASK:
|
||||||
|
case TEGRA210_MBDRC_MASTER_VOLUME:
|
||||||
|
case TEGRA210_MBDRC_FAST_FACTOR:
|
||||||
|
case TEGRA210_MBDRC_IIR_CONFIG:
|
||||||
|
case TEGRA210_MBDRC_IN_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_IN_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_FAST_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_IN_THRESHOLD:
|
||||||
|
case TEGRA210_MBDRC_OUT_THRESHOLD:
|
||||||
|
case TEGRA210_MBDRC_RATIO_1ST:
|
||||||
|
case TEGRA210_MBDRC_RATIO_2ND:
|
||||||
|
case TEGRA210_MBDRC_RATIO_3RD:
|
||||||
|
case TEGRA210_MBDRC_RATIO_4TH:
|
||||||
|
case TEGRA210_MBDRC_RATIO_5TH:
|
||||||
|
case TEGRA210_MBDRC_MAKEUP_GAIN:
|
||||||
|
case TEGRA210_MBDRC_INIT_GAIN:
|
||||||
|
case TEGRA210_MBDRC_GAIN_ATTACK:
|
||||||
|
case TEGRA210_MBDRC_GAIN_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_FAST_RELEASE:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_mbdrc_volatile_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
if (reg >= TEGRA210_MBDRC_IIR_CONFIG)
|
||||||
|
reg -= ((reg - TEGRA210_MBDRC_IIR_CONFIG) %
|
||||||
|
(TEGRA210_MBDRC_FILTER_PARAM_STRIDE *
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT));
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_MBDRC_SOFT_RESET:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_mbdrc_precious_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
if (reg >= TEGRA210_MBDRC_IIR_CONFIG)
|
||||||
|
reg -= ((reg - TEGRA210_MBDRC_IIR_CONFIG) %
|
||||||
|
(TEGRA210_MBDRC_FILTER_PARAM_STRIDE *
|
||||||
|
TEGRA210_MBDRC_FILTER_COUNT));
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config tegra210_mbdrc_regmap_config = {
|
||||||
|
.name = "mbdrc",
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
.max_register = TEGRA210_MBDRC_MAX_REG,
|
||||||
|
.writeable_reg = tegra210_mbdrc_wr_reg,
|
||||||
|
.readable_reg = tegra210_mbdrc_rd_reg,
|
||||||
|
.volatile_reg = tegra210_mbdrc_volatile_reg,
|
||||||
|
.precious_reg = tegra210_mbdrc_precious_reg,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
int tegra210_mbdrc_codec_init(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
const struct tegra210_mbdrc_config *conf = &mbdrc_init_config;
|
||||||
|
u32 val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(codec->dev);
|
||||||
|
/* Initialize MBDRC registers and ahub-ram with default params */
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_MBDRC_MODE_MASK,
|
||||||
|
conf->mode << TEGRA210_MBDRC_CONFIG_MBDRC_MODE_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_RMS_OFFSET_MASK,
|
||||||
|
conf->rms_off << TEGRA210_MBDRC_CONFIG_RMS_OFFSET_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_PEAK_RMS_MASK,
|
||||||
|
conf->peak_rms_mode << TEGRA210_MBDRC_CONFIG_PEAK_RMS_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_FILTER_STRUCTURE_MASK,
|
||||||
|
conf->fliter_structure <<
|
||||||
|
TEGRA210_MBDRC_CONFIG_FILTER_STRUCTURE_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_SHIFT_CTRL_MASK,
|
||||||
|
conf->shift_ctrl << TEGRA210_MBDRC_CONFIG_SHIFT_CTRL_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CONFIG,
|
||||||
|
TEGRA210_MBDRC_CONFIG_FRAME_SIZE_MASK,
|
||||||
|
__ffs(conf->frame_size) <<
|
||||||
|
TEGRA210_MBDRC_CONFIG_FRAME_SIZE_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CHANNEL_MASK,
|
||||||
|
TEGRA210_MBDRC_CHANNEL_MASK_MASK,
|
||||||
|
conf->channel_mask << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR,
|
||||||
|
TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK,
|
||||||
|
conf->fa_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR,
|
||||||
|
TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK,
|
||||||
|
conf->fr_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT);
|
||||||
|
|
||||||
|
for (i = 0; i < MBDRC_NUM_BAND; i++) {
|
||||||
|
const struct tegra210_mbdrc_band_params *params =
|
||||||
|
&conf->band_params[i];
|
||||||
|
u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE;
|
||||||
|
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_IIR_CONFIG,
|
||||||
|
TEGRA210_MBDRC_IIR_CONFIG_NUM_STAGES_MASK,
|
||||||
|
params->iir_stages <<
|
||||||
|
TEGRA210_MBDRC_IIR_CONFIG_NUM_STAGES_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_IN_ATTACK,
|
||||||
|
TEGRA210_MBDRC_IN_ATTACK_TC_MASK,
|
||||||
|
params->in_attack_tc <<
|
||||||
|
TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_IN_RELEASE,
|
||||||
|
TEGRA210_MBDRC_IN_RELEASE_TC_MASK,
|
||||||
|
params->in_release_tc <<
|
||||||
|
TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_FAST_ATTACK,
|
||||||
|
TEGRA210_MBDRC_FAST_ATTACK_TC_MASK,
|
||||||
|
params->fast_attack_tc <<
|
||||||
|
TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT);
|
||||||
|
|
||||||
|
val = (((params->in_threshold[0] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_MASK) |
|
||||||
|
((params->in_threshold[1] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_MASK) |
|
||||||
|
((params->in_threshold[2] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_MASK) |
|
||||||
|
((params->in_threshold[3] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_MASK));
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_IN_THRESHOLD, 0xffffffff, val);
|
||||||
|
|
||||||
|
val = (((params->out_threshold[0] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_1ST_MASK) |
|
||||||
|
((params->out_threshold[1] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_2ND_MASK) |
|
||||||
|
((params->out_threshold[2] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_3RD_MASK) |
|
||||||
|
((params->out_threshold[3] >>
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_SHIFT) &
|
||||||
|
TEGRA210_MBDRC_THRESH_4TH_MASK));
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_OUT_THRESHOLD,
|
||||||
|
0xffffffff, val);
|
||||||
|
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_RATIO_1ST,
|
||||||
|
TEGRA210_MBDRC_RATIO_1ST_MASK,
|
||||||
|
params->ratio[0] << TEGRA210_MBDRC_RATIO_1ST_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_RATIO_2ND,
|
||||||
|
TEGRA210_MBDRC_RATIO_2ND_MASK,
|
||||||
|
params->ratio[1] << TEGRA210_MBDRC_RATIO_2ND_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_RATIO_3RD,
|
||||||
|
TEGRA210_MBDRC_RATIO_3RD_MASK,
|
||||||
|
params->ratio[2] << TEGRA210_MBDRC_RATIO_3RD_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_RATIO_4TH,
|
||||||
|
TEGRA210_MBDRC_RATIO_4TH_MASK,
|
||||||
|
params->ratio[3] << TEGRA210_MBDRC_RATIO_4TH_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_RATIO_5TH,
|
||||||
|
TEGRA210_MBDRC_RATIO_5TH_MASK,
|
||||||
|
params->ratio[4] << TEGRA210_MBDRC_RATIO_5TH_SHIFT);
|
||||||
|
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_MAKEUP_GAIN,
|
||||||
|
TEGRA210_MBDRC_MAKEUP_GAIN_MASK,
|
||||||
|
params->makeup_gain <<
|
||||||
|
TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_INIT_GAIN,
|
||||||
|
TEGRA210_MBDRC_INIT_GAIN_MASK,
|
||||||
|
params->gain_init <<
|
||||||
|
TEGRA210_MBDRC_INIT_GAIN_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_GAIN_ATTACK,
|
||||||
|
TEGRA210_MBDRC_GAIN_ATTACK_MASK,
|
||||||
|
params->gain_attack_tc <<
|
||||||
|
TEGRA210_MBDRC_GAIN_ATTACK_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_GAIN_RELEASE,
|
||||||
|
TEGRA210_MBDRC_GAIN_RELEASE_MASK,
|
||||||
|
params->gain_release_tc <<
|
||||||
|
TEGRA210_MBDRC_GAIN_RELEASE_SHIFT);
|
||||||
|
regmap_update_bits(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_FAST_RELEASE,
|
||||||
|
TEGRA210_MBDRC_FAST_RELEASE_MASK,
|
||||||
|
params->fast_release_tc <<
|
||||||
|
TEGRA210_MBDRC_FAST_RELEASE_SHIFT);
|
||||||
|
|
||||||
|
tegra210_xbar_write_ahubram(ope->mbdrc_regmap,
|
||||||
|
reg_off + TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL,
|
||||||
|
reg_off + TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA, 0,
|
||||||
|
(u32 *)¶ms->biquad_params[0],
|
||||||
|
TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5);
|
||||||
|
}
|
||||||
|
pm_runtime_put_sync(codec->dev);
|
||||||
|
|
||||||
|
snd_soc_add_codec_controls(codec, tegra210_mbdrc_controls,
|
||||||
|
ARRAY_SIZE(tegra210_mbdrc_controls));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_mbdrc_codec_init);
|
||||||
|
|
||||||
|
int tegra210_mbdrc_init(struct platform_device *pdev, int id)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = dev_get_drvdata(&pdev->dev);
|
||||||
|
struct resource *mem, *memregion;
|
||||||
|
void __iomem *regs;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, id);
|
||||||
|
if (!mem) {
|
||||||
|
dev_err(&pdev->dev, "No memory resource\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
memregion = devm_request_mem_region(&pdev->dev, mem->start,
|
||||||
|
resource_size(mem), pdev->name);
|
||||||
|
if (!memregion) {
|
||||||
|
dev_err(&pdev->dev, "Memory region already claimed\n");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
|
||||||
|
if (!regs) {
|
||||||
|
dev_err(&pdev->dev, "ioremap failed\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope->mbdrc_regmap = devm_regmap_init_mmio(&pdev->dev, regs,
|
||||||
|
&tegra210_mbdrc_regmap_config);
|
||||||
|
if (IS_ERR(ope->mbdrc_regmap)) {
|
||||||
|
dev_err(&pdev->dev, "regmap init failed\n");
|
||||||
|
ret = PTR_ERR(ope->mbdrc_regmap);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_mbdrc_init);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("Tegra210 MBDRC module");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
462
sound/soc/tegra-alt/tegra210_ope_alt.c
Normal file
462
sound/soc/tegra-alt/tegra210_ope_alt.c
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
/*
|
||||||
|
* tegra210_ope_alt.c - Tegra210 OPE driver
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <sound/core.h>
|
||||||
|
#include <sound/pcm.h>
|
||||||
|
#include <sound/pcm_params.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
|
#include "tegra210_xbar_alt.h"
|
||||||
|
#include "tegra210_ope_alt.h"
|
||||||
|
|
||||||
|
#define DRV_NAME "tegra210-ope"
|
||||||
|
|
||||||
|
static int tegra210_ope_runtime_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
regcache_cache_only(ope->mbdrc_regmap, true);
|
||||||
|
regcache_cache_only(ope->peq_regmap, true);
|
||||||
|
regcache_cache_only(ope->regmap, true);
|
||||||
|
clk_disable_unprepare(ope->clk_ope);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_ope_runtime_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(ope->clk_ope);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "clk_enable failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
regcache_cache_only(ope->regmap, false);
|
||||||
|
regcache_cache_only(ope->peq_regmap, false);
|
||||||
|
regcache_cache_only(ope->mbdrc_regmap, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
unsigned int reg)
|
||||||
|
{
|
||||||
|
int channels, audio_bits;
|
||||||
|
struct tegra210_xbar_cif_conf cif_conf;
|
||||||
|
|
||||||
|
channels = params_channels(params);
|
||||||
|
if (channels < 2)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (params_format(params)) {
|
||||||
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
|
audio_bits = TEGRA210_AUDIOCIF_BITS_16;
|
||||||
|
break;
|
||||||
|
case SNDRV_PCM_FORMAT_S32_LE:
|
||||||
|
audio_bits = TEGRA210_AUDIOCIF_BITS_32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cif_conf.threshold = 0;
|
||||||
|
cif_conf.audio_channels = channels;
|
||||||
|
cif_conf.client_channels = channels;
|
||||||
|
cif_conf.audio_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);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_ope_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
struct device *dev = dai->dev;
|
||||||
|
struct tegra210_ope *ope = snd_soc_dai_get_drvdata(dai);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* set RX cif and TX cif */
|
||||||
|
ret = tegra210_ope_set_audio_cif(ope, params,
|
||||||
|
TEGRA210_OPE_AXBAR_RX_CIF_CTRL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Can't set OPE RX CIF: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tegra210_ope_set_audio_cif(ope, params,
|
||||||
|
TEGRA210_OPE_AXBAR_TX_CIF_CTRL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Can't set OPE TX CIF: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_ope_codec_probe(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
codec->control_data = ope->regmap;
|
||||||
|
ret = snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
|
||||||
|
if (ret != 0) {
|
||||||
|
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope->soc_data->peq_soc_data.codec_init(codec);
|
||||||
|
ope->soc_data->mbdrc_soc_data.codec_init(codec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct snd_soc_dai_ops tegra210_ope_dai_ops = {
|
||||||
|
.hw_params = tegra210_ope_hw_params,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver tegra210_ope_dais[] = {
|
||||||
|
{
|
||||||
|
.name = "OPE IN",
|
||||||
|
.playback = {
|
||||||
|
.stream_name = "OPE Receive",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 8,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "OPE OUT",
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "OPE Transmit",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 8,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||||
|
},
|
||||||
|
.ops = &tegra210_ope_dai_ops,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_dapm_widget tegra210_ope_widgets[] = {
|
||||||
|
SND_SOC_DAPM_AIF_IN("OPE RX", NULL, 0, SND_SOC_NOPM,
|
||||||
|
0, 0),
|
||||||
|
SND_SOC_DAPM_AIF_OUT("OPE TX", NULL, 0, TEGRA210_OPE_ENABLE,
|
||||||
|
TEGRA210_OPE_EN_SHIFT, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_dapm_route tegra210_ope_routes[] = {
|
||||||
|
{ "OPE RX", NULL, "OPE Receive" },
|
||||||
|
{ "OPE TX", NULL, "OPE RX" },
|
||||||
|
{ "OPE Transmit", NULL, "OPE TX" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new tegra210_ope_controls[] = {
|
||||||
|
SOC_SINGLE("direction peq to mbdrc", TEGRA210_OPE_DIRECTION,
|
||||||
|
TEGRA210_OPE_DIRECTION_SHIFT, 1, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_codec_driver tegra210_ope_codec = {
|
||||||
|
.probe = tegra210_ope_codec_probe,
|
||||||
|
.dapm_widgets = tegra210_ope_widgets,
|
||||||
|
.num_dapm_widgets = ARRAY_SIZE(tegra210_ope_widgets),
|
||||||
|
.dapm_routes = tegra210_ope_routes,
|
||||||
|
.num_dapm_routes = ARRAY_SIZE(tegra210_ope_routes),
|
||||||
|
.controls = tegra210_ope_controls,
|
||||||
|
.num_controls = ARRAY_SIZE(tegra210_ope_controls),
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool tegra210_ope_wr_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_MASK:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_CLEAR:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_CIF_CTRL:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_MASK:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_CLEAR:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_CIF_CTRL:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_ENABLE:
|
||||||
|
case TEGRA210_OPE_SOFT_RESET:
|
||||||
|
case TEGRA210_OPE_CG:
|
||||||
|
case TEGRA210_OPE_DIRECTION:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_ope_rd_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_MASK:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_CLEAR:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_CIF_CTRL:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_MASK:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_CLEAR:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_CIF_CTRL:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_ENABLE:
|
||||||
|
case TEGRA210_OPE_SOFT_RESET:
|
||||||
|
case TEGRA210_OPE_CG:
|
||||||
|
case TEGRA210_OPE_STATUS:
|
||||||
|
case TEGRA210_OPE_INT_STATUS:
|
||||||
|
case TEGRA210_OPE_DIRECTION:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_ope_volatile_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_RX_INT_STATUS:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_STATUS:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_SET:
|
||||||
|
case TEGRA210_OPE_AXBAR_TX_INT_STATUS:
|
||||||
|
|
||||||
|
case TEGRA210_OPE_SOFT_RESET:
|
||||||
|
case TEGRA210_OPE_STATUS:
|
||||||
|
case TEGRA210_OPE_INT_STATUS:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config tegra210_ope_regmap_config = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
.max_register = TEGRA210_OPE_DIRECTION,
|
||||||
|
.writeable_reg = tegra210_ope_wr_reg,
|
||||||
|
.readable_reg = tegra210_ope_rd_reg,
|
||||||
|
.volatile_reg = tegra210_ope_volatile_reg,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra210_ope_soc_data soc_data_tegra210 = {
|
||||||
|
.set_audio_cif = tegra210_xbar_set_cif,
|
||||||
|
.peq_soc_data = {
|
||||||
|
.init = tegra210_peq_init,
|
||||||
|
.codec_init = tegra210_peq_codec_init,
|
||||||
|
},
|
||||||
|
.mbdrc_soc_data = {
|
||||||
|
.init = tegra210_mbdrc_init,
|
||||||
|
.codec_init = tegra210_mbdrc_codec_init,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id tegra210_ope_of_match[] = {
|
||||||
|
{ .compatible = "nvidia,tegra210-ope", .data = &soc_data_tegra210 },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra210_ope_platform_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope;
|
||||||
|
struct resource *mem, *memregion;
|
||||||
|
void __iomem *regs;
|
||||||
|
int ret = 0;
|
||||||
|
const struct of_device_id *match;
|
||||||
|
struct tegra210_ope_soc_data *soc_data;
|
||||||
|
|
||||||
|
pr_info("OPE platform probe\n");
|
||||||
|
|
||||||
|
match = of_match_device(tegra210_ope_of_match, &pdev->dev);
|
||||||
|
if (!match) {
|
||||||
|
dev_err(&pdev->dev, "Error: No device match found\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
soc_data = (struct tegra210_ope_soc_data *)match->data;
|
||||||
|
|
||||||
|
ope = devm_kzalloc(&pdev->dev, sizeof(struct tegra210_ope), GFP_KERNEL);
|
||||||
|
if (!ope) {
|
||||||
|
dev_err(&pdev->dev, "Can't allocate ope\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
dev_set_drvdata(&pdev->dev, ope);
|
||||||
|
|
||||||
|
ope->soc_data = soc_data;
|
||||||
|
|
||||||
|
ope->clk_ope = devm_clk_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(ope->clk_ope)) {
|
||||||
|
dev_err(&pdev->dev, "Can't retrieve ope clock\n");
|
||||||
|
ret = PTR_ERR(ope->clk_ope);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!mem) {
|
||||||
|
dev_err(&pdev->dev, "No memory resource\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
memregion = devm_request_mem_region(&pdev->dev, mem->start,
|
||||||
|
resource_size(mem), pdev->name);
|
||||||
|
if (!memregion) {
|
||||||
|
dev_err(&pdev->dev, "Memory region already claimed\n");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
|
||||||
|
if (!regs) {
|
||||||
|
dev_err(&pdev->dev, "ioremap failed\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
|
||||||
|
&tegra210_ope_regmap_config);
|
||||||
|
if (IS_ERR(ope->regmap)) {
|
||||||
|
dev_err(&pdev->dev, "regmap init failed\n");
|
||||||
|
ret = PTR_ERR(ope->regmap);
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
regcache_cache_only(ope->regmap, true);
|
||||||
|
|
||||||
|
ret = ope->soc_data->peq_soc_data.init(pdev,
|
||||||
|
TEGRA210_PEQ_IORESOURCE_MEM);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "peq init failed\n");
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
regcache_cache_only(ope->peq_regmap, true);
|
||||||
|
|
||||||
|
ret = ope->soc_data->mbdrc_soc_data.init(pdev,
|
||||||
|
TEGRA210_MBDRC_IORESOURCE_MEM);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "mbdrc init failed\n");
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
regcache_cache_only(ope->mbdrc_regmap, true);
|
||||||
|
|
||||||
|
if (of_property_read_u32(pdev->dev.of_node,
|
||||||
|
"nvidia,ahub-ope-id",
|
||||||
|
&pdev->dev.id) < 0) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"Missing property nvidia,ahub-ope-id\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_clk_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
if (!pm_runtime_enabled(&pdev->dev)) {
|
||||||
|
ret = tegra210_ope_runtime_resume(&pdev->dev);
|
||||||
|
if (ret)
|
||||||
|
goto err_pm_disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_soc_register_codec(&pdev->dev, &tegra210_ope_codec,
|
||||||
|
tegra210_ope_dais,
|
||||||
|
ARRAY_SIZE(tegra210_ope_dais));
|
||||||
|
if (ret != 0) {
|
||||||
|
dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
|
||||||
|
goto err_suspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("OPE platform probe successful\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_suspend:
|
||||||
|
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||||
|
tegra210_ope_runtime_suspend(&pdev->dev);
|
||||||
|
err_pm_disable:
|
||||||
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
err_clk_put:
|
||||||
|
devm_clk_put(&pdev->dev, ope->clk_ope);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_ope_platform_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = dev_get_drvdata(&pdev->dev);
|
||||||
|
snd_soc_unregister_codec(&pdev->dev);
|
||||||
|
|
||||||
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||||
|
tegra210_ope_runtime_suspend(&pdev->dev);
|
||||||
|
|
||||||
|
devm_clk_put(&pdev->dev, ope->clk_ope);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops tegra210_ope_pm_ops = {
|
||||||
|
SET_RUNTIME_PM_OPS(tegra210_ope_runtime_suspend,
|
||||||
|
tegra210_ope_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver tegra210_ope_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = DRV_NAME,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = tegra210_ope_of_match,
|
||||||
|
.pm = &tegra210_ope_pm_ops,
|
||||||
|
},
|
||||||
|
.probe = tegra210_ope_platform_probe,
|
||||||
|
.remove = tegra210_ope_platform_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(tegra210_ope_driver)
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("Tegra210 OPE ASoC driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:" DRV_NAME);
|
||||||
|
MODULE_DEVICE_TABLE(of, tegra210_ope_of_match);
|
||||||
316
sound/soc/tegra-alt/tegra210_peq_alt.c
Normal file
316
sound/soc/tegra-alt/tegra210_peq_alt.c
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* tegra210_peq_alt.c - Tegra210 PEQ driver
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <sound/core.h>
|
||||||
|
#include <sound/pcm.h>
|
||||||
|
#include <sound/pcm_params.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
|
#include "tegra210_xbar_alt.h"
|
||||||
|
#include "tegra210_ope_alt.h"
|
||||||
|
#include "tegra210_peq_alt.h"
|
||||||
|
|
||||||
|
/* Default PEQ filter parameters for a 5-stage biquad*/
|
||||||
|
static const int biquad_init_stage = 5;
|
||||||
|
static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = {
|
||||||
|
1495012349, /* pre-gain */
|
||||||
|
/* Gains : b0, b1, a0, a1, a2 */
|
||||||
|
536870912, -1073741824, 536870912, 2143508246, -1069773768, /* band-0 */
|
||||||
|
134217728, -265414508, 131766272, 2140402222, -1071252997, /* band-1 */
|
||||||
|
268435456, -233515765, -33935948, 1839817267, -773826124, /* band-2 */
|
||||||
|
536870912, -672537913, 139851540, 1886437554, -824433167, /* band-3 */
|
||||||
|
268435456, -114439279, 173723964, 205743566, 278809729, /* band-4 */
|
||||||
|
1, 0, 0, 0, 0, /* band-5 */
|
||||||
|
1, 0, 0, 0, 0, /* band-6 */
|
||||||
|
1, 0, 0, 0, 0, /* band-7 */
|
||||||
|
1, 0, 0, 0, 0, /* band-8 */
|
||||||
|
1, 0, 0, 0, 0, /* band-9 */
|
||||||
|
1, 0, 0, 0, 0, /* band-10 */
|
||||||
|
1, 0, 0, 0, 0, /* band-11 */
|
||||||
|
963423114, /* post-gain */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = {
|
||||||
|
23, /* pre-shift */
|
||||||
|
30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* shift for bands */
|
||||||
|
28, /* post-shift */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra210_peq_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
regmap_read(ope->peq_regmap, mc->reg, &val);
|
||||||
|
ucontrol->value.integer.value[0] = (val >> mc->shift) & mask;
|
||||||
|
if (mc->invert)
|
||||||
|
ucontrol->value.integer.value[0] =
|
||||||
|
mc->max - ucontrol->value.integer.value[0];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_peq_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
val = (ucontrol->value.integer.value[0] & mask);
|
||||||
|
if (mc->invert)
|
||||||
|
val = mc->max - val;
|
||||||
|
val = val << mc->shift;
|
||||||
|
|
||||||
|
return regmap_update_bits(ope->peq_regmap, mc->reg,
|
||||||
|
(mask << mc->shift), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_peq_ahub_ram_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
|
||||||
|
memset(data, 0, params->soc.num_regs * codec->val_bytes);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra210_peq_ahub_ram_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
u32 reg_ctrl = params->soc.base;
|
||||||
|
u32 reg_data = reg_ctrl + codec->val_bytes;
|
||||||
|
u32 *data = (u32 *)ucontrol->value.bytes.data;
|
||||||
|
|
||||||
|
tegra210_xbar_write_ahubram(ope->peq_regmap, reg_ctrl, reg_data,
|
||||||
|
params->shift, data, params->soc.num_regs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \
|
||||||
|
TEGRA_SOC_BYTES_EXT("peq channel" #chan " biquad gain params", \
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_CTRL, \
|
||||||
|
TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \
|
||||||
|
(TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \
|
||||||
|
tegra210_peq_ahub_ram_get, tegra210_peq_ahub_ram_put)
|
||||||
|
|
||||||
|
#define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \
|
||||||
|
TEGRA_SOC_BYTES_EXT("peq channel" #chan " biquad shift params", \
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_CTRL, \
|
||||||
|
TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \
|
||||||
|
(TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \
|
||||||
|
tegra210_peq_ahub_ram_get, tegra210_peq_ahub_ram_put)
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new tegra210_peq_controls[] = {
|
||||||
|
SOC_SINGLE_EXT("peq active", TEGRA210_PEQ_CONFIG,
|
||||||
|
TEGRA210_PEQ_CONFIG_MODE_SHIFT, 1, 0,
|
||||||
|
tegra210_peq_get, tegra210_peq_put),
|
||||||
|
SOC_SINGLE_EXT("peq biquad stages", TEGRA210_PEQ_CONFIG,
|
||||||
|
TEGRA210_PEQ_CONFIG_BIQUAD_STAGES_SHIFT,
|
||||||
|
TEGRA210_PEQ_MAX_BIQUAD_STAGES - 1, 0,
|
||||||
|
tegra210_peq_get, tegra210_peq_put),
|
||||||
|
|
||||||
|
TEGRA210_PEQ_GAIN_PARAMS_CTRL(0),
|
||||||
|
TEGRA210_PEQ_GAIN_PARAMS_CTRL(1),
|
||||||
|
|
||||||
|
TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0),
|
||||||
|
TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_PEQ_SOFT_RESET:
|
||||||
|
case TEGRA210_PEQ_CG:
|
||||||
|
case TEGRA210_PEQ_CONFIG:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_PEQ_SOFT_RESET:
|
||||||
|
case TEGRA210_PEQ_CG:
|
||||||
|
case TEGRA210_PEQ_STATUS:
|
||||||
|
case TEGRA210_PEQ_CONFIG:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_PEQ_SOFT_RESET:
|
||||||
|
case TEGRA210_PEQ_STATUS:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_CTRL:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_DATA:
|
||||||
|
case TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config tegra210_peq_regmap_config = {
|
||||||
|
.name = "peq",
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
.max_register = TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA,
|
||||||
|
.writeable_reg = tegra210_peq_wr_reg,
|
||||||
|
.readable_reg = tegra210_peq_rd_reg,
|
||||||
|
.volatile_reg = tegra210_peq_volatile_reg,
|
||||||
|
.precious_reg = tegra210_peq_precious_reg,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
int tegra210_peq_codec_init(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = snd_soc_codec_get_drvdata(codec);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(codec->dev);
|
||||||
|
regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CONFIG,
|
||||||
|
TEGRA210_PEQ_CONFIG_MODE_MASK,
|
||||||
|
0 << TEGRA210_PEQ_CONFIG_MODE_SHIFT);
|
||||||
|
regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CONFIG,
|
||||||
|
TEGRA210_PEQ_CONfIG_BIQUAD_STAGES_MASK,
|
||||||
|
(biquad_init_stage - 1) <<
|
||||||
|
TEGRA210_PEQ_CONFIG_BIQUAD_STAGES_SHIFT);
|
||||||
|
|
||||||
|
/* Initialize PEQ AHUB RAM with default params */
|
||||||
|
for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
|
||||||
|
/* Set default gain params */
|
||||||
|
tegra210_xbar_write_ahubram(ope->peq_regmap,
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_CTRL,
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_DATA,
|
||||||
|
(i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
|
||||||
|
(u32 *)&biquad_init_gains,
|
||||||
|
TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
|
||||||
|
|
||||||
|
/* Set default shift params */
|
||||||
|
tegra210_xbar_write_ahubram(ope->peq_regmap,
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_CTRL,
|
||||||
|
TEGRA210_PEQ_AHUBRAMCTL_CONFIG_RAM_SHIFT_DATA,
|
||||||
|
(i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
|
||||||
|
(u32 *)&biquad_init_shifts,
|
||||||
|
TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
|
||||||
|
}
|
||||||
|
pm_runtime_put_sync(codec->dev);
|
||||||
|
|
||||||
|
snd_soc_add_codec_controls(codec, tegra210_peq_controls,
|
||||||
|
ARRAY_SIZE(tegra210_peq_controls));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_peq_codec_init);
|
||||||
|
|
||||||
|
int tegra210_peq_init(struct platform_device *pdev, int id)
|
||||||
|
{
|
||||||
|
struct tegra210_ope *ope = dev_get_drvdata(&pdev->dev);
|
||||||
|
struct resource *mem, *memregion;
|
||||||
|
void __iomem *regs;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, id);
|
||||||
|
if (!mem) {
|
||||||
|
dev_err(&pdev->dev, "No memory resource\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
memregion = devm_request_mem_region(&pdev->dev, mem->start,
|
||||||
|
resource_size(mem), pdev->name);
|
||||||
|
if (!memregion) {
|
||||||
|
dev_err(&pdev->dev, "Memory region already claimed\n");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
|
||||||
|
if (!regs) {
|
||||||
|
dev_err(&pdev->dev, "ioremap failed\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope->peq_regmap = devm_regmap_init_mmio(&pdev->dev, regs,
|
||||||
|
&tegra210_peq_regmap_config);
|
||||||
|
if (IS_ERR(ope->peq_regmap)) {
|
||||||
|
dev_err(&pdev->dev, "regmap init failed\n");
|
||||||
|
ret = PTR_ERR(ope->peq_regmap);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_peq_init);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("Tegra210 PEQ module");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@@ -769,6 +769,8 @@ struct of_dev_auxdata tegra210_xbar_auxdata[] = {
|
|||||||
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4000, "tegra210-dmic.0", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4000, "tegra210-dmic.0", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4100, "tegra210-dmic.1", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4100, "tegra210-dmic.1", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4200, "tegra210-dmic.2", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra210-dmic", 0x702d4200, "tegra210-dmic.2", NULL),
|
||||||
|
OF_DEV_AUXDATA("nvidia,tegra210-ope", 0x702d8000, "tegra210-ope.0", NULL),
|
||||||
|
OF_DEV_AUXDATA("nvidia,tegra210-ope", 0x702d8400, "tegra210-ope.1", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra210-amixer", 0x702dbb00, "tegra210-mixer", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra210-amixer", 0x702dbb00, "tegra210-mixer", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra210-spdif", 0x702d6000, "tegra210-spdif", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra210-spdif", 0x702d6000, "tegra210-spdif", NULL),
|
||||||
{}
|
{}
|
||||||
@@ -961,6 +963,50 @@ void tegra210_xbar_set_cif(struct regmap *regmap, unsigned int reg,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tegra210_xbar_set_cif);
|
EXPORT_SYMBOL_GPL(tegra210_xbar_set_cif);
|
||||||
|
|
||||||
|
void tegra210_xbar_write_ahubram(struct regmap *regmap, unsigned int reg_ctrl,
|
||||||
|
unsigned int reg_data, unsigned int ram_offset,
|
||||||
|
unsigned int *data, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
val = (ram_offset << TEGRA210_AHUBRAMCTL_CTRL_RAM_ADDR_SHIFT) &
|
||||||
|
TEGRA210_AHUBRAMCTL_CTRL_RAM_ADDR_MASK;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_ADDR_INIT_EN;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_SEQ_ACCESS_EN;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_RW_WRITE;
|
||||||
|
|
||||||
|
regmap_write(regmap, reg_ctrl, val);
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
regmap_write(regmap, reg_data, data[i]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_xbar_write_ahubram);
|
||||||
|
|
||||||
|
void tegra210_xbar_read_ahubram(struct regmap *regmap, unsigned int reg_ctrl,
|
||||||
|
unsigned int reg_data, unsigned int ram_offset,
|
||||||
|
unsigned int *data, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
val = (ram_offset << TEGRA210_AHUBRAMCTL_CTRL_RAM_ADDR_SHIFT) &
|
||||||
|
TEGRA210_AHUBRAMCTL_CTRL_RAM_ADDR_MASK;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_ADDR_INIT_EN;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_SEQ_ACCESS_EN;
|
||||||
|
val |= TEGRA210_AHUBRAMCTL_CTRL_RW_READ;
|
||||||
|
|
||||||
|
regmap_write(regmap, reg_ctrl, val);
|
||||||
|
/* Since all ahub non-io modules work under same ahub clock it is not
|
||||||
|
necessary to check ahub read busy bit after every read */
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
regmap_read(regmap, reg_data, &data[i]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra210_xbar_read_ahubram);
|
||||||
|
|
||||||
int tegra210_xbar_read_reg (unsigned int reg, unsigned int *val)
|
int tegra210_xbar_read_reg (unsigned int reg, unsigned int *val)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user