mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
audio:add ti2558 speaker protection
add ti2558 speaker protection related code. add ko in kbuild for sofiar Change-Id: I6c7aa5c53bff4724a4fc3d2a6df07433c7ee71a6 Signed-off-by: liaohj <liaohj@lenovo.com> Reviewed-on: https://gerrit.mot.com/1405309 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou <zhouwl@motorola.com> Reviewed-by: Hujun Liao <liaohj@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
1e2e9b8b64
commit
636b9f2ed8
6 changed files with 1159 additions and 42 deletions
|
|
@ -20,7 +20,7 @@ EXTRA_CFLAGS += -DCONFIG_TAS2560_REGMAP -DCONFIG_TAS2560_CODEC -DCONFIG_TAS2560_
|
|||
endif
|
||||
|
||||
ifneq (,$(filter sofiar%, $(TARGET_PRODUCT)))
|
||||
EXTRA_CFLAGS += -DCONFIG_TAS2562_REGMAP -DCONFIG_TAS2562_CODEC -DCONFIG_SND_SOC_TAS2562 -DTAS2558_CODEC
|
||||
EXTRA_CFLAGS += -DCONFIG_TAS2562_REGMAP -DCONFIG_TAS2562_CODEC -DCONFIG_SND_SOC_TAS2562 -DTAS2558_CODEC -DCONFIG_TAS25XX_ALGO -DCONFIG_TAS25XX_ALGO_STEREO
|
||||
endif
|
||||
|
||||
ifneq (,$(filter rav%, $(TARGET_PRODUCT)))
|
||||
|
|
@ -58,5 +58,5 @@ obj-m += tas2560_algo.o
|
|||
tas2560_calib-objs = tas2560-calib.o
|
||||
obj-m += tas2560_calib.o
|
||||
|
||||
tas2562-objs = tas2562-codec.o tas2562-regmap.o
|
||||
tas2562-objs = tas2562-codec.o tas2562-regmap.o tas25xx-algo.o tas25xx-calib.o
|
||||
obj-m += tas2562.o
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@
|
|||
|
||||
#include "tas2562.h"
|
||||
|
||||
#ifdef CONFIG_TAS25XX_ALGO
|
||||
#include <dsp/tas_smart_amp_v2.h>
|
||||
#include "tas25xx-calib.h"
|
||||
#endif /*CONFIG_TAS25XX_ALGO*/
|
||||
|
||||
#define TAS2562_MDELAY 0xFFFFFFFE
|
||||
#define TAS2562_MSLEEP 0xFFFFFFFD
|
||||
#define TAS2562_IVSENSER_ENABLE 1
|
||||
|
|
@ -93,7 +98,7 @@ static unsigned int tas2562_codec_read(struct snd_soc_codec *codec,
|
|||
{
|
||||
struct tas2562_priv *p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
dev_err(p_tas2562->dev, "Should not get here\n");
|
||||
dev_dbg(p_tas2562->dev, "Should not get here\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -128,7 +133,7 @@ static int tas2562iv_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct tas2562_priv *p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
struct tas2562_priv *p_tas2562 = NULL;
|
||||
int iv_enable = 0, n_result = 0;
|
||||
|
||||
if (codec == NULL) {
|
||||
|
|
@ -136,6 +141,12 @@ static int tas2562iv_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
if (p_tas2562 == NULL) {
|
||||
pr_err("%s:p_tas2562 is NULL\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iv_enable = ucontrol->value.integer.value[0];
|
||||
|
||||
n_result = tas2562_iv_enable(p_tas2562, iv_enable);
|
||||
|
|
@ -149,9 +160,20 @@ static int tas2562iv_get(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct tas2562_priv *p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
struct tas2562_priv *p_tas2562 = NULL;
|
||||
int ret, value;
|
||||
|
||||
if (codec == NULL) {
|
||||
pr_err("%s:codec is NULL\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
if (p_tas2562 == NULL) {
|
||||
pr_err("%s:p_tas2562 is NULL\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = p_tas2562->read(p_tas2562, channel_left,
|
||||
TAS2562_POWERCONTROL, &value);
|
||||
if (ret < 0)
|
||||
|
|
@ -183,7 +205,7 @@ static int tas2562_codec_write(struct snd_soc_codec *codec, unsigned int reg,
|
|||
{
|
||||
struct tas2562_priv *p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
dev_err(p_tas2562->dev, "Should not get here\n");
|
||||
dev_dbg(p_tas2562->dev, "Should not get here\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -245,6 +267,7 @@ static int tas2562_i2c_load_data(struct tas2562_priv *p_tas2562,
|
|||
return n_result;
|
||||
}
|
||||
|
||||
#ifdef CODEC_PM
|
||||
static int tas2562_codec_suspend(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct tas2562_priv *p_tas2562 = snd_soc_codec_get_drvdata(codec);
|
||||
|
|
@ -272,6 +295,7 @@ static int tas2562_codec_resume(struct snd_soc_codec *codec)
|
|||
mutex_unlock(&p_tas2562->codec_lock);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tas2562_set_power_state(struct tas2562_priv *p_tas2562,
|
||||
enum channel chn, int state)
|
||||
|
|
@ -376,16 +400,12 @@ static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
|
|||
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||
SND_SOC_DAPM_OUTPUT("OUT"),
|
||||
SND_SOC_DAPM_SIGGEN("VMON"),
|
||||
SND_SOC_DAPM_SIGGEN("IMON")
|
||||
SND_SOC_DAPM_OUTPUT("OUT")
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route tas2562_audio_map[] = {
|
||||
{"DAC", NULL, "ASI1"},
|
||||
{"OUT", NULL, "DAC"},
|
||||
{"Voltage Sense", NULL, "VMON"},
|
||||
{"Current Sense", NULL, "IMON"},
|
||||
{"OUT", NULL, "DAC"}
|
||||
};
|
||||
|
||||
static int tas2562_get_left_speaker_switch(struct snd_kcontrol *pKcontrol,
|
||||
|
|
@ -512,6 +532,7 @@ static int tas2562_set_slot(struct tas2562_priv *p_tas2562, int slot_width)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
dev_info(p_tas2562->dev, "%s: slot_width = %d\n", __func__, slot_width);
|
||||
switch (slot_width) {
|
||||
case 16:
|
||||
ret = p_tas2562->update_bits(p_tas2562, channel_both,
|
||||
|
|
@ -955,10 +976,17 @@ static int tas2562_load_init(struct tas2562_priv *p_tas2562)
|
|||
TAS2562_MISCCONFIGURATIONREG0, 0xcf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = p_tas2562->write(p_tas2562, channel_both,
|
||||
TAS2562_TDMConfigurationReg4, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if(p_tas2562->mn_channels == 2) {
|
||||
ret = p_tas2562->write(p_tas2562, channel_both,
|
||||
TAS2562_TDMConfigurationReg4, 0x11);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
ret = p_tas2562->write(p_tas2562, channel_both,
|
||||
TAS2562_TDMConfigurationReg4, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = p_tas2562->write(p_tas2562, channel_both,
|
||||
TAS2562_CLOCKCONFIGURATION, 0x0c);
|
||||
if (ret < 0)
|
||||
|
|
@ -984,6 +1012,10 @@ static int tas2562_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
tas2562_load_init(p_tas2562);
|
||||
tas2562_iv_enable(p_tas2562, 1);
|
||||
#ifdef CONFIG_TAS25XX_ALGO
|
||||
tas_smartamp_add_algo_controls(codec);
|
||||
#endif //CONFIG_TAS25XX_ALGO
|
||||
|
||||
dev_err(p_tas2562->dev, "%s\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
|
@ -991,6 +1023,10 @@ static int tas2562_codec_probe(struct snd_soc_codec *codec)
|
|||
|
||||
static int tas2562_codec_remove(struct snd_soc_codec *codec)
|
||||
{
|
||||
#ifdef CONFIG_TAS25XX_ALGO
|
||||
tas_smartamp_remove_algo_controls(codec);
|
||||
#endif //CONFIG_TAS25XX_ALGO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1023,8 +1059,10 @@ static struct snd_soc_codec_driver soc_codec_driver_tas2562 = {
|
|||
.remove = tas2562_codec_remove,
|
||||
.read = tas2562_codec_read,
|
||||
.write = tas2562_codec_write,
|
||||
#ifdef CODEC_PM
|
||||
.suspend = tas2562_codec_suspend,
|
||||
.resume = tas2562_codec_resume,
|
||||
#endif
|
||||
.component_driver = {
|
||||
.controls = tas2562_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(tas2562_snd_controls),
|
||||
|
|
|
|||
|
|
@ -830,6 +830,34 @@ static int tas2562_runtime_resume(struct tas2562_priv *p_tas2562)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tas2562_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct tas2562_priv *p_tas2562 = dev_get_drvdata(dev);
|
||||
|
||||
if(!p_tas2562){
|
||||
dev_err(p_tas2562->dev, "drvdata is NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&p_tas2562->codec_lock);
|
||||
tas2562_runtime_suspend(p_tas2562);
|
||||
mutex_unlock(&p_tas2562->codec_lock);
|
||||
return 0;
|
||||
}
|
||||
static int tas2562_pm_resume(struct device *dev)
|
||||
{
|
||||
struct tas2562_priv *p_tas2562 = dev_get_drvdata(dev);
|
||||
|
||||
if(!p_tas2562){
|
||||
dev_err(p_tas2562->dev, "drvdata is NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&p_tas2562->codec_lock);
|
||||
tas2562_runtime_resume(p_tas2562);
|
||||
mutex_unlock(&p_tas2562->codec_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas2562_parse_dt(struct device *dev, struct tas2562_priv *p_tas2562)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
|
|
@ -863,16 +891,6 @@ static int tas2562_parse_dt(struct device *dev, struct tas2562_priv *p_tas2562)
|
|||
p_tas2562->mn_l_addr);
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "ti,right-channel",
|
||||
&p_tas2562->mn_r_addr);
|
||||
if (rc) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
"ti,right-channel", np->full_name, rc);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,right-channel=0x%x",
|
||||
p_tas2562->mn_r_addr);
|
||||
}
|
||||
|
||||
p_tas2562->mn_reset_gpio = of_get_named_gpio(np, "ti,reset-gpio", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_reset_gpio)) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
|
|
@ -883,16 +901,6 @@ static int tas2562_parse_dt(struct device *dev, struct tas2562_priv *p_tas2562)
|
|||
p_tas2562->mn_reset_gpio);
|
||||
}
|
||||
|
||||
p_tas2562->mn_reset_gpio2 = of_get_named_gpio(np, "ti,reset-gpio2", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_reset_gpio2)) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
"ti,reset-gpio2", np->full_name,
|
||||
p_tas2562->mn_reset_gpio2);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,reset-gpio2=%d",
|
||||
p_tas2562->mn_reset_gpio2);
|
||||
}
|
||||
|
||||
p_tas2562->mn_irq_gpio = of_get_named_gpio(np, "ti,irq-gpio", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_irq_gpio)) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
|
|
@ -902,13 +910,35 @@ static int tas2562_parse_dt(struct device *dev, struct tas2562_priv *p_tas2562)
|
|||
p_tas2562->mn_irq_gpio);
|
||||
}
|
||||
|
||||
p_tas2562->mn_irq_gpio2 = of_get_named_gpio(np, "ti,irq-gpio2", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_irq_gpio2)) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
if(p_tas2562->mn_channels != 1) {
|
||||
rc = of_property_read_u32(np, "ti,right-channel",
|
||||
&p_tas2562->mn_r_addr);
|
||||
if (rc) {
|
||||
dev_err(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
"ti,right-channel", np->full_name, rc);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,right-channel=0x%x",
|
||||
p_tas2562->mn_r_addr);
|
||||
}
|
||||
|
||||
p_tas2562->mn_reset_gpio2 = of_get_named_gpio(np, "ti,reset-gpio2", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_reset_gpio2)) {
|
||||
dev_dbg(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
"ti,reset-gpio2", np->full_name,
|
||||
p_tas2562->mn_reset_gpio2);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,reset-gpio2=%d",
|
||||
p_tas2562->mn_reset_gpio2);
|
||||
}
|
||||
|
||||
p_tas2562->mn_irq_gpio2 = of_get_named_gpio(np, "ti,irq-gpio2", 0);
|
||||
if (!gpio_is_valid(p_tas2562->mn_irq_gpio2)) {
|
||||
dev_dbg(p_tas2562->dev, "Looking up %s property in node %s failed %d\n",
|
||||
"ti,irq-gpio2", np->full_name, p_tas2562->mn_irq_gpio2);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,irq-gpio2=%d",
|
||||
p_tas2562->mn_irq_gpio2);
|
||||
} else {
|
||||
dev_dbg(p_tas2562->dev, "ti,irq-gpio2=%d",
|
||||
p_tas2562->mn_irq_gpio2);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -978,9 +1008,12 @@ static int tas2562_i2c_probe(struct i2c_client *p_client,
|
|||
p_tas2562->update_bits = tas2562_dev_update_bits;
|
||||
p_tas2562->hw_reset = tas2562_hw_reset;
|
||||
p_tas2562->enable_irq = tas2562_enable_irq;
|
||||
#ifdef CODEC_PM
|
||||
p_tas2562->runtime_suspend = tas2562_runtime_suspend;
|
||||
p_tas2562->runtime_resume = tas2562_runtime_resume;
|
||||
p_tas2562->mn_power_state = TAS2562_POWER_SHUTDOWN;
|
||||
#endif
|
||||
p_tas2562->mn_power_state = TAS2562_POWER_SHUTDOWN;
|
||||
p_tas2562->spk_l_control = 1;
|
||||
|
||||
mutex_init(&p_tas2562->dev_lock);
|
||||
|
|
@ -1117,6 +1150,10 @@ static const struct of_device_id tas2562_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, tas2562_of_match);
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops tas2562_pm_ops = {
|
||||
.suspend = tas2562_pm_suspend,
|
||||
.resume = tas2562_pm_resume
|
||||
};
|
||||
|
||||
static struct i2c_driver tas2562_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
@ -1125,6 +1162,7 @@ static struct i2c_driver tas2562_i2c_driver = {
|
|||
#if defined(CONFIG_OF)
|
||||
.of_match_table = of_match_ptr(tas2562_of_match),
|
||||
#endif
|
||||
.pm = &tas2562_pm_ops,
|
||||
},
|
||||
.probe = tas2562_i2c_probe,
|
||||
.remove = tas2562_i2c_remove,
|
||||
|
|
|
|||
822
sound/soc/codecs/tas25xx-algo.c
Normal file
822
sound/soc/codecs/tas25xx-algo.c
Normal file
|
|
@ -0,0 +1,822 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <dsp/q6afe-v2.h>
|
||||
#include <dsp/tas_smart_amp_v2.h>
|
||||
#include "tas25xx-calib.h"
|
||||
|
||||
#define USE_VFS 1
|
||||
#define CODEC_CONTROL 1
|
||||
#define CONFIG_SET_RE_IN_KERNEL
|
||||
#define POISON_VAL 0xDEADDEAD
|
||||
#define MAX_STRING (300)
|
||||
#define SMARTAMP_SPEAKER_CALIBDATA_FILE "/mnt/vendor/persist/factory/audio/tas25xx_calib.bin"
|
||||
|
||||
/*Master Control to Bypass the Smartamp TI CAPIv2 module*/
|
||||
static int s_tas_smartamp_bypass = 0;
|
||||
static int s_tas_smartamp_enable = 0;
|
||||
static struct mutex routing_lock;
|
||||
|
||||
#ifdef CONFIG_SET_RE_IN_KERNEL
|
||||
static int get_calibrated_re_tcalib (uint32_t *rdc_fix, uint32_t *tv_fix, int channel_count)
|
||||
{
|
||||
struct file *file = NULL;
|
||||
char calib_data[MAX_STRING] = {0};
|
||||
char filepath[128] = SMARTAMP_SPEAKER_CALIBDATA_FILE;
|
||||
mm_segment_t fs;
|
||||
int ret = 0;
|
||||
|
||||
static int s_rdc_fix[2] = {POISON_VAL, POISON_VAL};
|
||||
static int s_tv_fix = POISON_VAL;
|
||||
|
||||
#if USE_VFS
|
||||
loff_t pos = 0;
|
||||
#else
|
||||
int size;
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
if ((s_rdc_fix[0] == POISON_VAL) &&
|
||||
(s_rdc_fix[1] == POISON_VAL)
|
||||
)
|
||||
{
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
#if USE_VFS
|
||||
file = filp_open(filepath, O_RDONLY, 0);
|
||||
if(!IS_ERR(file))
|
||||
{
|
||||
vfs_read(file, calib_data, MAX_STRING-1, &pos);
|
||||
|
||||
if (channel_count == 1) {
|
||||
if(sscanf(calib_data, "%d;%d;", s_rdc_fix, &s_tv_fix) != 2) {
|
||||
pr_err("[Smartamp:%s] file %s read error\n", __func__, filepath);
|
||||
ret = -EIO;
|
||||
}
|
||||
} else if (channel_count == 2) {
|
||||
if(sscanf(calib_data, "%d;%d;%d;", &s_rdc_fix[0], &s_rdc_fix[1], &s_tv_fix) != 3) {
|
||||
pr_err("[Smartamp:%s] file %s read error\n", __func__, filepath);
|
||||
ret = -EIO;
|
||||
}
|
||||
}
|
||||
filp_close(file, NULL);
|
||||
|
||||
} else {
|
||||
pr_err("[Smartamp:%s] file %s open failed %p \n ", __func__, filepath, file);
|
||||
ret = -EIO;
|
||||
}
|
||||
#else
|
||||
fd = sys_open (filepath, O_RDONLY, 0);
|
||||
if (fd > 0) {
|
||||
memset (calib_data, 0, sizeof(calib_data));
|
||||
size = sys_read (fd, calib_data, MAX_STRING-1);
|
||||
sys_close (fd);
|
||||
|
||||
pr_info ("TI-SmartPA: *** sys_read size = %d", size);
|
||||
|
||||
if (channel_count == 1) {
|
||||
if(sscanf(calib_data, "%d;%d;", &rdc_fix[0], tv_fix) != 2) {
|
||||
pr_err("[TI-SmartPA:%s] file %s read error\n", __func__, filepath);
|
||||
ret = -EIO;
|
||||
}
|
||||
} else if (channel_count == 2) {
|
||||
if(sscanf(calib_data, "%d;%d;%d;", &rdc_fix[0], &rdc_fix[1], tv_fix) != 3) {
|
||||
pr_err("[TI-SmartPA:%s] file %s read error\n", __func__, filepath);
|
||||
ret = -EIO;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pr_err("[TI-SmartPA:%s] file %s open failed %p \n ", __func__, filepath, file);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
set_fs(fs);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (rdc_fix) {
|
||||
rdc_fix[0] = (uint32_t)s_rdc_fix[0];
|
||||
|
||||
if (channel_count == 2) {
|
||||
rdc_fix[1] = (uint32_t)s_rdc_fix[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (tv_fix)
|
||||
*tv_fix = (uint32_t)s_tv_fix;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif //CONFIG_SET_RE_IN_KERNEL
|
||||
|
||||
static int tas25xx_smartamp_get_set(u8 *user_data, uint32_t param_id,
|
||||
uint8_t get_set, uint32_t length, uint32_t module_id)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (get_set) {
|
||||
case TAS_SET_PARAM:
|
||||
if (s_tas_smartamp_bypass) {
|
||||
pr_err("TI-SmartPA: %s: SmartAmp is bypassed no control set", __func__);
|
||||
goto fail_cmd;
|
||||
}
|
||||
ret = afe_tas_smartamp_set_calib_data(module_id, param_id, length, user_data);
|
||||
break;
|
||||
|
||||
case TAS_GET_PARAM:
|
||||
memset(user_data, 0, length);
|
||||
ret = afe_tas_smartamp_get_calib_data(module_id, param_id, length, user_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
fail_cmd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Wrapper arround set/get parameter, all set/get commands pass through this wrapper*/
|
||||
int tas25xx_smartamp_algo_ctrl(u8 *user_data, uint32_t param_id,
|
||||
uint8_t get_set, uint32_t length, uint32_t module_id)
|
||||
{
|
||||
int ret = 0;
|
||||
mutex_lock(&routing_lock);
|
||||
ret = tas25xx_smartamp_get_set(user_data, param_id, get_set, length, module_id);
|
||||
mutex_unlock(&routing_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tas25xx_smartamp_algo_ctrl);
|
||||
|
||||
/*Control-1: Set Profile*/
|
||||
static const char *profile_index_text[] = { "NONE", TAS_ALGO_PROFILE_LIST, "CALIB"};
|
||||
static const struct soc_enum profile_index_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(profile_index_text), profile_index_text),
|
||||
};
|
||||
|
||||
static int tas25xx_set_profile(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret;
|
||||
int profile_id = pUcontrol->value.integer.value[0];
|
||||
int param_id = 0;
|
||||
int max_number_of_profiles = sizeof(profile_index_text)/sizeof(profile_index_text[0]);
|
||||
if (profile_id >= max_number_of_profiles)
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("TI-SmartPA: %s: Setting profile %s", __func__, profile_index_text[profile_id]);
|
||||
if(profile_id)
|
||||
profile_id -= 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_PROFILE, 1, CHANNEL0);
|
||||
pr_info("TI-SmartPA: %s: Sending set profile", __func__);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&profile_id, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0)
|
||||
pr_err("TI-SmartPA: %s: Failed to set config", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_profile(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret;
|
||||
int profile_id = 0;
|
||||
int param_id = 0;
|
||||
int max_number_of_profiles = sizeof(profile_index_text)/sizeof(profile_index_text[0]);
|
||||
|
||||
|
||||
if(s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_PROFILE, 1, CHANNEL0);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&profile_id, param_id,
|
||||
TAS_GET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to get profile", __func__);
|
||||
profile_id = 0;
|
||||
} else {
|
||||
profile_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pUcontrol->value.integer.value[0] = profile_id;
|
||||
|
||||
if (profile_id < max_number_of_profiles) {
|
||||
pr_info("TI-SmartPA: %s: getting profile %s", __func__, profile_index_text[profile_id]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Control-2: Set Calibrated Rdc*/
|
||||
static int tas25xx_set_Re_common (int re_value_in, int channel)
|
||||
{
|
||||
int ret;
|
||||
int param_id = 0;
|
||||
int re_value = re_value_in;
|
||||
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, channel);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&re_value, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_set_Re_left(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int re_value = pUcontrol->value.integer.value[0];
|
||||
|
||||
pr_info("TI-SmartPA: %s: Setting Re %d", __func__, re_value);
|
||||
return tas25xx_set_Re_common(re_value, CHANNEL0);
|
||||
}
|
||||
|
||||
static int tas25xx_dummy_get(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
pUcontrol->value.integer.value[0] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_dummy_set(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Control-3: Calibration and Test(F0,Q,Tv) Controls*/
|
||||
static const char *tas25xx_calib_test_text[] = {
|
||||
"NONE",
|
||||
"CALIB_START",
|
||||
"CALIB_STOP",
|
||||
"TEST_START",
|
||||
"TEST_STOP"
|
||||
};
|
||||
|
||||
static const struct soc_enum tas25xx_calib_test_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_calib_test_text), tas25xx_calib_test_text),
|
||||
};
|
||||
|
||||
static int tas25xx_calib_test_set_common (int calib_command, int channel)
|
||||
{
|
||||
int ret = 0;
|
||||
int param_id = 0;
|
||||
int data = 1;
|
||||
|
||||
switch(calib_command) {
|
||||
case CALIB_START:
|
||||
pr_info ("TI-SmartPA: %s: CALIB_START", __func__);
|
||||
param_id = TAS_CALC_PARAM_IDX (TAS_SA_CALIB_INIT, 1, channel);
|
||||
break;
|
||||
|
||||
case CALIB_STOP:
|
||||
pr_info ("TI-SmartPA: %s: CALIB_STOP", __func__);
|
||||
param_id = TAS_CALC_PARAM_IDX (TAS_SA_CALIB_DEINIT, 1, channel);
|
||||
break;
|
||||
|
||||
case TEST_START:
|
||||
case TEST_STOP:
|
||||
default:
|
||||
pr_info ("TI-SmartPA: %s: no impl", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (param_id) {
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&data, param_id,
|
||||
TAS_SET_PARAM, sizeof (uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to set calib/test, ret=%d", __func__, ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_calib_test_set(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
int user_data = pUcontrol->value.integer.value[0];
|
||||
if ((0 == (ret = tas25xx_calib_test_set_common (user_data, CHANNEL0)))) {
|
||||
#ifdef CONFIG_TAS25XX_ALGO_STEREO
|
||||
ret = tas25xx_calib_test_set_common (user_data, CHANNEL1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-4: Get Re*/
|
||||
//returns -ve error or +ve re value, 0 if not called
|
||||
static int tas25xx_get_re_common (int channel)
|
||||
{
|
||||
int ret = 0;
|
||||
int re_value = 0;
|
||||
int param_id = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s, channel=%d", __func__, channel);
|
||||
|
||||
if(s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX (TAS_SA_GET_RE, 1, channel);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&re_value, param_id,
|
||||
TAS_GET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to get Re", __func__);
|
||||
} else {
|
||||
ret = re_value;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_re_left(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = tas25xx_get_re_common (CHANNEL0);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
ret = 0;
|
||||
pr_info("TI-SmartPA: %s: Getting Re %d", __func__, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-5: Get F0*/
|
||||
static int tas25xx_get_f0_common(int channel)
|
||||
{
|
||||
int f0_value = 0;
|
||||
int param_id = 0;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s, channel=%d", __func__, channel);
|
||||
|
||||
if(s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_F0, 1, channel);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&f0_value, param_id,
|
||||
TAS_GET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err ("TI-SmartPA: %s: Failed to get F0", __func__);
|
||||
} else {
|
||||
ret = f0_value;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_f0_left(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = tas25xx_get_f0_common (CHANNEL0);
|
||||
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting F0 val=%d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-6: Get Q*/
|
||||
static int tas25xx_get_q_common (int channel)
|
||||
{
|
||||
int ret = 0;
|
||||
int q_value = 0;
|
||||
int param_id = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s, channel=%d", __func__, channel);
|
||||
|
||||
if (s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX (TAS_SA_GET_Q, 1, channel);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&q_value, param_id,
|
||||
TAS_GET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err ("TI-SmartPA: %s: Failed to get F0", __func__);
|
||||
} else {
|
||||
ret = q_value;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_q_left(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = tas25xx_get_q_common (CHANNEL0);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting Q %d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-7: Get Tv*/
|
||||
static int tas25xx_get_tv_common(int channel)
|
||||
{
|
||||
int ret = 0;
|
||||
int tv_value = 0;
|
||||
int param_id = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s, channel=%d", __func__, channel);
|
||||
|
||||
if (s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_GET_TV, 1, channel);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&tv_value, param_id,
|
||||
TAS_GET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err ("TI-SmartPA: %s: Failed to get Tv", __func__);
|
||||
} else {
|
||||
ret = tv_value;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_tv_left(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
|
||||
int ret = tas25xx_get_tv_common (CHANNEL0);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting Tv %d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-8: Smartamp Enable*/
|
||||
static const char *tas25xx_smartamp_enable_text[] = {
|
||||
"DISABLE",
|
||||
"ENABLE"
|
||||
};
|
||||
|
||||
static const struct soc_enum tas25xx_smartamp_enable_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_smartamp_enable_text), tas25xx_smartamp_enable_text),
|
||||
};
|
||||
|
||||
static int tas25xx_smartamp_enable_set(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int param_id = 0;
|
||||
int user_data = pUcontrol->value.integer.value[0];
|
||||
#ifdef CONFIG_SET_RE_IN_KERNEL
|
||||
uint32_t calibration_data[3];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TAS25XX_ALGO_STEREO
|
||||
int number_of_ch = 2;
|
||||
#else
|
||||
int number_of_ch = 1;
|
||||
#endif
|
||||
pr_info("TI-SmartPA: %s: case %d, number_of_ch=%d", __func__, user_data, number_of_ch);
|
||||
|
||||
s_tas_smartamp_enable = user_data;
|
||||
if (s_tas_smartamp_enable == 0) {
|
||||
pr_info("TI-SmartPA: %s: Disable called", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_info ("TI-SmartPA: %s: Setting the feedback module info for TAS", __func__);
|
||||
ret = afe_spk_prot_feed_back_cfg (TAS_TX_PORT,TAS_RX_PORT, 1, 0, 1);
|
||||
if (ret) {
|
||||
pr_err("TI-SmartPA: %s: FB Path Info failed ignoring ret = 0x%x", __func__, ret);
|
||||
}
|
||||
|
||||
|
||||
pr_info ("TI-SmartPA: %s: Sending TX Enable", __func__);
|
||||
param_id = CAPI_V2_TAS_TX_ENABLE;
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&user_data, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_TX);
|
||||
if (ret) {
|
||||
pr_err("TI-SmartPA: %s: TX Enable Failed ret = 0x%x", __func__, ret);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
//Special configuration indicating bin file
|
||||
user_data = 0xB1B1B1B1;
|
||||
pr_info("TI-SmartPA: %s: Sending TX Config", __func__);
|
||||
param_id = CAPI_V2_TAS_TX_CFG;
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_TX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to set config", __func__);
|
||||
}
|
||||
|
||||
user_data = 1;
|
||||
pr_info ("TI-SmartPA: %s: Sending RX Enable", __func__);
|
||||
param_id = CAPI_V2_TAS_RX_ENABLE;
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&user_data, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret) {
|
||||
pr_err("TI-SmartPA: %s: RX Enable Failed ret = 0x%x", __func__, ret);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
//Special configuration indicating bin file
|
||||
user_data = 0xB1B1B1B1;
|
||||
pr_info("TI-SmartPA: %s: Sending RX Config", __func__);
|
||||
param_id = CAPI_V2_TAS_RX_CFG;
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&user_data, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to set config", __func__);
|
||||
}
|
||||
|
||||
s_tas_smartamp_enable = true;
|
||||
|
||||
#ifdef CONFIG_SET_RE_IN_KERNEL
|
||||
if (number_of_ch == 2) {
|
||||
ret = get_calibrated_re_tcalib (calibration_data, &calibration_data[2], number_of_ch);
|
||||
} else {
|
||||
ret = get_calibrated_re_tcalib (calibration_data, &calibration_data[1], number_of_ch);
|
||||
}
|
||||
if(ret) {
|
||||
pr_err("[Smartamp:%s] unable to get the calibration data = 0x%x", __func__, ret);
|
||||
} else {
|
||||
int32_t t_cal;
|
||||
if (number_of_ch == 2) {
|
||||
t_cal = calibration_data[2];
|
||||
pr_info("[Smartamp:%s] setting re %d,%d and tcal %d", __func__
|
||||
, calibration_data[0], calibration_data[1], calibration_data[2]);
|
||||
} else {
|
||||
t_cal = calibration_data[1];
|
||||
pr_info("[Smartamp:%s] setting re %d and tcal %d", __func__
|
||||
, calibration_data[0], calibration_data[1]);
|
||||
}
|
||||
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_TCAL, 1, CHANNEL0);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&t_cal,
|
||||
param_id, TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("[Smartamp:%s] Failed to set Tcal", __func__);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, CHANNEL0);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)(&(calibration_data[0])),
|
||||
param_id, TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to set Re", __func__);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
if (number_of_ch == 2) {
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_RE, 1, CHANNEL1);
|
||||
ret = tas25xx_smartamp_algo_ctrl ((u8 *)&(calibration_data[1]),
|
||||
param_id, TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if(ret < 0) {
|
||||
pr_err("TI-SmartPA: %s: Failed to set Re", __func__);
|
||||
goto fail_cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_SET_RE_IN_KERNEL
|
||||
|
||||
fail_cmd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_smartamp_enable_get(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int user_data = s_tas_smartamp_enable;
|
||||
pUcontrol->value.integer.value[0] = user_data;
|
||||
pr_info("TI-SmartPA: %s: case %d(0=DISABLE, 1=ENABLE)", __func__, user_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control-9: Smartamp Bypass */
|
||||
static const char *tas25xx_smartamp_bypass_text[] = {
|
||||
"FALSE",
|
||||
"TRUE"
|
||||
};
|
||||
|
||||
static const struct soc_enum tas25xx_smartamp_bypass_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tas25xx_smartamp_bypass_text), tas25xx_smartamp_bypass_text),
|
||||
};
|
||||
|
||||
static int tas25xx_smartamp_bypass_set(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int user_data = pUcontrol->value.integer.value[0];
|
||||
if (s_tas_smartamp_enable) {
|
||||
pr_debug("TI-SmartPA: %s: cannot update while smartamp enabled", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s_tas_smartamp_bypass = user_data;
|
||||
pr_info("TI-SmartPA: %s: case %d(FALSE=0,TRUE=1)", __func__, user_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_smartamp_bypass_get(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
pUcontrol->value.integer.value[0] = s_tas_smartamp_bypass;
|
||||
pr_info("TI-SmartPA: %s: case %d", __func__, s_tas_smartamp_bypass);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_set_spk_id(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int speaker_id = pUcontrol->value.integer.value[0];
|
||||
int param_id = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s: spk-id set %d", __func__, speaker_id);
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_SPKID, 1, CHANNEL0);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&speaker_id, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err ("TI-SmartPA: %s: Failed to set spk id", __func__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_set_t_calib(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int calib_temp = pUcontrol->value.integer.value[0];
|
||||
int param_id = 0;
|
||||
|
||||
pr_info("TI-SmartPA: %s: tcalib set %d", __func__, calib_temp);
|
||||
if (s_tas_smartamp_enable) {
|
||||
param_id = TAS_CALC_PARAM_IDX(TAS_SA_SET_TCAL, 1, CHANNEL0);
|
||||
ret = tas25xx_smartamp_algo_ctrl((u8 *)&calib_temp, param_id,
|
||||
TAS_SET_PARAM, sizeof(uint32_t), AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret < 0) {
|
||||
pr_err ("TI-SmartPA: %s: Failed to set spk id", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TAS25XX_ALGO_STEREO
|
||||
static int tas25xx_set_Re_right(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int re_value = pUcontrol->value.integer.value[0];
|
||||
|
||||
pr_info("TI-SmartPA: %s: Setting Re %d", __func__, re_value);
|
||||
return tas25xx_set_Re_common(re_value, CHANNEL1);
|
||||
}
|
||||
|
||||
static int tas25xx_get_re_right(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tas25xx_get_re_common (CHANNEL1);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
ret = 0;
|
||||
pr_info("TI-SmartPA: %s: Getting Re value=%d", __func__, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_f0_right(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = tas25xx_get_f0_common (CHANNEL1);
|
||||
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting F0 valu=%d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_q_right(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
int ret = tas25xx_get_q_common (CHANNEL1);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting Q val=%d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas25xx_get_tv_right(struct snd_kcontrol *pKcontrol,
|
||||
struct snd_ctl_elem_value *pUcontrol)
|
||||
{
|
||||
|
||||
int ret = tas25xx_get_tv_common (CHANNEL1);
|
||||
if (ret >= 0) {
|
||||
pUcontrol->value.integer.value[0] = ret;
|
||||
pr_info("TI-SmartPA: %s: Getting Tv %d", __func__, ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct snd_kcontrol_new smartamp_tas25xx_mixer_controls[] = {
|
||||
SOC_ENUM_EXT("TAS25XX_ALGO_PROFILE", profile_index_enum[0],
|
||||
tas25xx_get_profile, tas25xx_set_profile),
|
||||
SOC_ENUM_EXT("TAS25XX_ALGO_CALIB_TEST", tas25xx_calib_test_enum[0],
|
||||
tas25xx_dummy_get, tas25xx_calib_test_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_SET_SPK_ID", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_dummy_get, tas25xx_set_spk_id),
|
||||
SOC_SINGLE_EXT("TAS25XX_SET_T_CALIB", SND_SOC_NOPM, 0, 100, 0,
|
||||
tas25xx_dummy_get, tas25xx_set_t_calib),
|
||||
|
||||
//left
|
||||
SOC_SINGLE_EXT("TAS25XX_SET_RE_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_dummy_get, tas25xx_set_Re_left),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_RE_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_re_left, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_F0_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_f0_left, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_Q_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_q_left, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_TV_LEFT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_tv_left, tas25xx_dummy_set),
|
||||
|
||||
//Right
|
||||
#ifdef CONFIG_TAS25XX_ALGO_STEREO
|
||||
SOC_SINGLE_EXT("TAS25XX_SET_RE_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_dummy_get, tas25xx_set_Re_right),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_RE_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_re_right, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_F0_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_f0_right, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_Q_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_q_right, tas25xx_dummy_set),
|
||||
SOC_SINGLE_EXT("TAS25XX_GET_TV_RIGHT", SND_SOC_NOPM, 0, 0x7fffffff, 0,
|
||||
tas25xx_get_tv_right, tas25xx_dummy_set),
|
||||
#endif
|
||||
|
||||
SOC_ENUM_EXT("TAS25XX_SMARTPA_ENABLE", tas25xx_smartamp_enable_enum[0],
|
||||
tas25xx_smartamp_enable_get, tas25xx_smartamp_enable_set),
|
||||
|
||||
SOC_ENUM_EXT("TAS25XX_ALGO_BYPASS", tas25xx_smartamp_bypass_enum[0],
|
||||
tas25xx_smartamp_bypass_get, tas25xx_smartamp_bypass_set),
|
||||
};
|
||||
|
||||
#if CODEC_CONTROL
|
||||
void tas_smartamp_add_algo_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
pr_err("TI-SmartPA: %s: Adding smartamp controls", __func__);
|
||||
mutex_init(&routing_lock);
|
||||
snd_soc_add_codec_controls(codec, smartamp_tas25xx_mixer_controls,
|
||||
ARRAY_SIZE(smartamp_tas25xx_mixer_controls));
|
||||
tas_calib_init();
|
||||
}
|
||||
EXPORT_SYMBOL(tas_smartamp_add_algo_controls);
|
||||
#else
|
||||
void tas_smartamp_add_algo_controls_for_platform (struct snd_soc_platform *platform)
|
||||
{
|
||||
pr_err("TI-SmartPA: %s: Adding smartamp controls", __func__);
|
||||
mutex_init(&routing_lock);
|
||||
snd_soc_add_platform_controls (platform, smartamp_tas25xx_mixer_controls, ARRAY_SIZE(smartamp_tas25xx_mixer_controls));
|
||||
tas_calib_init();
|
||||
}
|
||||
EXPORT_SYMBOL(tas_smartamp_add_algo_controls_for_platform);
|
||||
#endif
|
||||
|
||||
void tas_smartamp_remove_algo_controls(struct snd_soc_codec *codec)
|
||||
{
|
||||
(void)codec;
|
||||
tas_calib_exit();
|
||||
}
|
||||
EXPORT_SYMBOL(tas_smartamp_remove_algo_controls);
|
||||
|
||||
MODULE_AUTHOR("Texas Instrumnets Inc.");
|
||||
MODULE_DESCRIPTION("TAS25xx ALSA SOC Smart Amplifier algo driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
191
sound/soc/codecs/tas25xx-calib.c
Normal file
191
sound/soc/codecs/tas25xx-calib.c
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
** =============================================================================
|
||||
** Copyright (c) 2017 Texas Instruments Inc.
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it under
|
||||
** the terms of the GNU General Public License as published by the Free Software
|
||||
** Foundation; version 2.
|
||||
**
|
||||
** This program is distributed in the hope that 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.
|
||||
**
|
||||
** File:
|
||||
** tas25xx-calib.c
|
||||
**
|
||||
** Description:
|
||||
** misc driver for interfacing for Texas Instruments TAS25xx algorithm
|
||||
**
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <dsp/tas_smart_amp_v2.h>
|
||||
|
||||
/* Holds the Packet data required for processing */
|
||||
struct tas_dsp_pkt {
|
||||
u8 slave_id;
|
||||
u8 book;
|
||||
u8 page;
|
||||
u8 offset;
|
||||
u8 data[TAS_PAYLOAD_SIZE * 4];
|
||||
};
|
||||
|
||||
static int smartamp_params_ctrl(uint8_t *input, u8 dir, u8 count)
|
||||
{
|
||||
u32 length = count / 4;
|
||||
u32 paramid = 0;
|
||||
u32 index;
|
||||
int ret = 0;
|
||||
int special_index = 0;
|
||||
struct tas_dsp_pkt *ppacket;
|
||||
|
||||
ppacket = (struct tas_dsp_pkt*)kmalloc (sizeof(struct tas_dsp_pkt), GFP_KERNEL);
|
||||
if (!ppacket) {
|
||||
pr_err ("TI-SmartPA: %s: kmalloc failed!", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(ppacket, 0, sizeof(struct tas_dsp_pkt));
|
||||
ret = copy_from_user (ppacket, input, sizeof(struct tas_dsp_pkt));
|
||||
if (ret){
|
||||
pr_err("TI-SmartPA: %s: Error copying from user\n", __func__);
|
||||
kfree (ppacket);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
index = (ppacket->page - 1) * 30 + (ppacket->offset - 8) / 4;
|
||||
special_index = TAS_SA_IS_SPL_IDX(index);
|
||||
pr_info("TI-SmartPA: %s: index = %d", __func__, index);
|
||||
if (special_index == 0) {
|
||||
if ((index < 0 || index > MAX_DSP_PARAM_INDEX)) {
|
||||
pr_err("TI-SmartPA: %s: invalid index !\n", __func__);
|
||||
kfree(ppacket);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
pr_info("TI-SmartPA: %s: Valid Index. special = %s\n", __func__, special_index ? "Yes" : "No");
|
||||
|
||||
/* speakers are differentiated by slave ids */
|
||||
if (ppacket->slave_id == SLAVE1 )
|
||||
{
|
||||
paramid = (paramid | (index ) | (length << 16) | (1 << 24));
|
||||
pr_err("TI-SmartPA: %s: Rcvd Slave id for slave 1, %x\n", __func__, ppacket->slave_id);
|
||||
}else if (ppacket->slave_id == SLAVE2 )
|
||||
{
|
||||
paramid = (paramid | (index ) | (length << 16) | (2 << 24));
|
||||
pr_err("TI-SmartPA: %s: Rcvd Slave id for slave 2, %x\n", __func__, ppacket->slave_id);
|
||||
}else{
|
||||
pr_err("TI-SmartPA: %s: Wrong slaveid = %x\n", __func__, ppacket->slave_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: In any case calculated paramid should not match with
|
||||
*/
|
||||
if ((paramid == CAPI_V2_TAS_RX_ENABLE) ||
|
||||
(paramid == CAPI_V2_TAS_TX_ENABLE) ||
|
||||
(paramid == CAPI_V2_TAS_RX_CFG) ||
|
||||
(paramid == CAPI_V2_TAS_TX_CFG))
|
||||
{
|
||||
pr_err("TI-SmartPA: %s: %s Slave 0x%x params failed, paramid mismatch\n", __func__,
|
||||
dir == TAS_GET_PARAM ? "get" : "set", ppacket->slave_id);
|
||||
kfree(ppacket);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tas25xx_smartamp_algo_ctrl(ppacket->data, paramid,
|
||||
dir, length * 4, AFE_SMARTAMP_MODULE_RX);
|
||||
if (ret)
|
||||
pr_err("TI-SmartPA: %s: %s Slave 0x%x params failed from afe, ret=%x\n", __func__,
|
||||
dir == TAS_GET_PARAM ? "get" : "set", ppacket->slave_id, ret);
|
||||
else
|
||||
pr_info("TI-SmartPA: %s: Algo control returned %d\n", __func__, ret);
|
||||
|
||||
if (dir == TAS_GET_PARAM) {
|
||||
ret = copy_to_user(input, ppacket, sizeof(struct tas_dsp_pkt));
|
||||
if (ret) {
|
||||
pr_err("TI-SmartPA: %s: Error copying to user after DSP", __func__);
|
||||
ret = -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(ppacket);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas_calib_open(struct inode *inode, struct file *fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tas_calib_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *offp)
|
||||
{
|
||||
int rc = 0;
|
||||
rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_SET_PARAM, count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t tas_calib_read(struct file *file, char __user *buffer,
|
||||
size_t count, loff_t *ptr)
|
||||
{
|
||||
int rc;
|
||||
rc = smartamp_params_ctrl((uint8_t *)buffer, TAS_GET_PARAM, count);
|
||||
if (rc < 0)
|
||||
count = rc;
|
||||
return count;
|
||||
}
|
||||
|
||||
static long tas_calib_ioctl(struct file *filp, uint cmd, ulong arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tas_calib_release(struct inode *inode, struct file *fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct file_operations tas_calib_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tas_calib_open,
|
||||
.write = tas_calib_write,
|
||||
.read = tas_calib_read,
|
||||
.release = tas_calib_release,
|
||||
.unlocked_ioctl = tas_calib_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice tas_calib_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "tas_calib",
|
||||
.fops = &tas_calib_fops,
|
||||
};
|
||||
|
||||
int tas_calib_init(void)
|
||||
{
|
||||
int rc;
|
||||
pr_err("TI-SmartPA: %s",__func__);
|
||||
rc = misc_register(&tas_calib_misc);
|
||||
if (rc)
|
||||
pr_err("TI-SmartPA: %s: register calib misc failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void tas_calib_exit(void)
|
||||
{
|
||||
misc_deregister(&tas_calib_misc);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Texas Instruments Inc.");
|
||||
MODULE_DESCRIPTION("tas2560 Misc driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
28
sound/soc/codecs/tas25xx-calib.h
Normal file
28
sound/soc/codecs/tas25xx-calib.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
** =============================================================================
|
||||
** Copyright (c) 2016 Texas Instruments Inc.
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it under
|
||||
** the terms of the GNU General Public License as published by the Free Software
|
||||
** Foundation; version 2.
|
||||
**
|
||||
** This program is distributed in the hope that 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.
|
||||
**
|
||||
** File:
|
||||
** tas25xx-calib.h
|
||||
**
|
||||
** Description:
|
||||
** header file for tas25xx-calib.c
|
||||
**
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _TAS25XX_CALIB_H_
|
||||
#define _TAS25XX_CALIB_H_
|
||||
|
||||
int tas_calib_init(void);
|
||||
void tas_calib_exit(void);
|
||||
|
||||
#endif /* _TAS25XX_CALIB_H */
|
||||
Loading…
Reference in a new issue