kernel_samsung_a53x/sound/soc/samsung/abox/abox_atune.c
2024-06-15 16:02:09 -03:00

2322 lines
74 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ALSA SoC - Samsung Abox Audio Tuning Block driver
*
* Copyright (c) 2020 Samsung Electronics Co. Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <sound/tlv.h>
#include "abox_soc.h"
#include "abox.h"
#include "abox_cmpnt.h"
#include "abox_dma.h"
#include "abox_atune.h"
#include "abox_memlog.h"
#define VERBOSE 1
#undef GAIN_CONTROL
#define COUNT_CH 8
#define COUNT_EQ 5
#ifdef GAIN_CONTROL
struct atune_gain_control {
unsigned int base;
unsigned int count;
unsigned int min;
unsigned int max;
};
static int atune_gain_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
struct device *dev = cmpnt->dev;
struct atune_gain_control *params = (void *)kcontrol->private_value;
abox_dbg(dev, "%s: %s\n", __func__, kcontrol->id.name);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = params->count;
uinfo->value.integer.min = params->min;
uinfo->value.integer.max = params->max;
return 0;
}
static int atune_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct device *dev = cmpnt->dev;
struct atune_gain_control *params = (void *)kcontrol->private_value;
unsigned int i;
int ret = 0;
abox_dbg(dev, "%s: %s\n", __func__, kcontrol->id.name);
for (i = 0; i < params->count; i++) {
unsigned int reg, val;
int index, shift, db;
reg = params->base + (i / ATUNE_FLD_PER_SFR(CH_GAIN));
val = snd_soc_component_read(cmpnt, reg);
if (ret < 0) {
abox_err(dev, "reading fail at %#x\n", reg);
break;
}
shift = (int)(val & ATUNE_CH_GAIN_SHIFT_MASK(i)) >>
ATUNE_CH_GAIN_SHIFT_L(i);
index = (int)(val & ATUNE_CH_GAIN_INDEX_MASK(i)) >>
ATUNE_CH_GAIN_INDEX_L(i);
db = shift * 6 + (index ? (index - 6) : 0);
if (VERBOSE)
abox_dbg(dev, "%s: shift:%d, index:%d, db:%d\n",
__func__, shift, index, db);
ucontrol->value.integer.value[i] = db;
abox_dbg(dev, "%s: %#x => %#x\n", kcontrol->id.name, reg, val);
}
return ret;
}
static int atune_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct device *dev = cmpnt->dev;
struct atune_gain_control *params = (void *)kcontrol->private_value;
unsigned int i;
abox_dbg(dev, "%s: %s\n", __func__, kcontrol->id.name);
for (i = 0; i < params->count; i++) {
unsigned int reg, val;
int index, shift, db;
db = (int)ucontrol->value.integer.value[i];
shift = db / 6;
index = db - (shift * 6);
index = index ? (index + 6) : 0;
if (VERBOSE)
abox_dbg(dev, "%s: shift:%d, index:%d, db:%d\n",
__func__, shift, index, db);
reg = params->base + (i / ATUNE_FLD_PER_SFR(CH_GAIN));
val = (shift << ATUNE_CH_GAIN_SHIFT_L(i)) |
(index << ATUNE_CH_GAIN_INDEX_L(i));
snd_soc_component_write(cmpnt, reg, val);
abox_dbg(dev, "%s: %#x <= %#x\n", kcontrol->id.name, reg, val);
}
return 0;
}
#define ATUNE_GAIN_CONTROL(xname, xbase, xcount, xmin, xmax) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.info = atune_gain_info, .get = atune_gain_get, \
.put = atune_gain_put, .private_value = \
((unsigned long)&(struct atune_gain_control) \
{.base = xbase, .count = xcount, \
.min = xmin, .max = xmax}) }
#endif
#define SOC_SINGLE_S_TLV(xname, reg, xshift, xmin, xmax, xsign_bit, \
xinvert, tlv_array) \
SOC_DOUBLE_R_S_TLV(xname, reg, reg, xshift, xmin, xmax, xsign_bit, \
xinvert, tlv_array)
static const char * const gain_func_texts[] = {
"MUTE", "NORMAL", "FADE IN", "FADE OUT",
};
static SOC_ENUM_SINGLE_DECL(spus0_pregain_func_enum, ATUNE_SPUS_USGAIN_CTRL(0),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spus1_pregain_func_enum, ATUNE_SPUS_USGAIN_CTRL(1),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spus0_postgain_func_enum, ATUNE_SPUS_DSGAIN_CTRL(0),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spus1_postgain_func_enum, ATUNE_SPUS_DSGAIN_CTRL(1),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spum0_pregain_func_enum, ATUNE_SPUM_USGAIN_CTRL(0),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spum1_pregain_func_enum, ATUNE_SPUM_USGAIN_CTRL(1),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spum0_postgain_func_enum, ATUNE_SPUM_DSGAIN_CTRL(0),
ATUNE_FUNC_L, gain_func_texts);
static SOC_ENUM_SINGLE_DECL(spum1_postgain_func_enum, ATUNE_SPUM_DSGAIN_CTRL(1),
ATUNE_FUNC_L, gain_func_texts);
static const DECLARE_TLV_DB_SCALE(atune_gain_shift_tlv, -19200, 600, 0);
static const DECLARE_TLV_DB_RANGE(atune_gain_index_tlv,
0x0, 0x0, TLV_DB_SCALE_ITEM(0, 0, 0),
0x1, 0x5, TLV_DB_SCALE_ITEM(-500, 100, 0),
);
#define ATUNE_SPUS_PREGAIN_CH_CONTROLS(x, ch) \
SOC_SINGLE_S_TLV("SPUS"#x" PREGAIN CH"#ch" Main Volume", \
ATUNE_SPUS_USGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_SHIFT_L(ch), \
-32, 20, 5, 0, atune_gain_shift_tlv), \
SOC_SINGLE_S_TLV("SPUS"#x" PREGAIN CH"#ch" Fine Volume", \
ATUNE_SPUS_USGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_INDEX_L(ch), \
0, 5, 2, 0, atune_gain_index_tlv)
#define ATUNE_SPUS_PREGAIN_CONTROLS(x) \
ATUNE_SPUS_PREGAIN_CH_CONTROLS(x, 0), \
ATUNE_SPUS_PREGAIN_CH_CONTROLS(x, 1), \
ATUNE_SPUS_PREGAIN_CH_CONTROLS(x, 2), \
ATUNE_SPUS_PREGAIN_CH_CONTROLS(x, 3)
#define ATUNE_SPUS_POSTGAIN_CH_CONTROLS(x, ch) \
SOC_SINGLE_S_TLV("SPUS"#x" POSTGAIN CH"#ch" Main Volume", \
ATUNE_SPUS_DSGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_SHIFT_L(ch), \
-32, 20, 5, 0, atune_gain_shift_tlv), \
SOC_SINGLE_S_TLV("SPUS"#x" POSTGAIN CH"#ch" Fine Volume", \
ATUNE_SPUS_DSGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_INDEX_L(ch), \
0, 5, 2, 0, atune_gain_index_tlv)
#define ATUNE_SPUS_POSTGAIN_CONTROLS(x) \
ATUNE_SPUS_POSTGAIN_CH_CONTROLS(x, 0), \
ATUNE_SPUS_POSTGAIN_CH_CONTROLS(x, 1), \
ATUNE_SPUS_POSTGAIN_CH_CONTROLS(x, 2), \
ATUNE_SPUS_POSTGAIN_CH_CONTROLS(x, 3)
static const char * const dither_type_texts[] = {
"OFF", "RPDF", "TPDF",
};
static SOC_ENUM_SINGLE_DECL(spus0_postgain_dither_type_enum,
ATUNE_SPUS_DSGAIN_BIT_CTRL(0), ATUNE_DITHER_TYPE_L,
dither_type_texts);
static SOC_ENUM_SINGLE_DECL(spus1_postgain_dither_type_enum,
ATUNE_SPUS_DSGAIN_BIT_CTRL(1), ATUNE_DITHER_TYPE_L,
dither_type_texts);
static SOC_ENUM_SINGLE_DECL(spum0_postgain_dither_type_enum,
ATUNE_SPUM_DSGAIN_BIT_CTRL(0), ATUNE_DITHER_TYPE_L,
dither_type_texts);
static SOC_ENUM_SINGLE_DECL(spum1_postgain_dither_type_enum,
ATUNE_SPUM_DSGAIN_BIT_CTRL(1), ATUNE_DITHER_TYPE_L,
dither_type_texts);
#define ATUNE_SPUM_PREGAIN_CH_CONTROLS(x, ch) \
SOC_SINGLE_S_TLV("SPUM"#x" PREGAIN CH"#ch" Main Volume", \
ATUNE_SPUM_USGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_SHIFT_L(ch), \
-32, 20, 5, 0, atune_gain_shift_tlv), \
SOC_SINGLE_S_TLV("SPUM"#x" PREGAIN CH"#ch" Fine Volume", \
ATUNE_SPUM_USGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_INDEX_L(ch), \
0, 5, 2, 0, atune_gain_index_tlv)
#define ATUNE_SPUM_PREGAIN_CONTROLS(x) \
ATUNE_SPUM_PREGAIN_CH_CONTROLS(x, 0), \
ATUNE_SPUM_PREGAIN_CH_CONTROLS(x, 1), \
ATUNE_SPUM_PREGAIN_CH_CONTROLS(x, 2), \
ATUNE_SPUM_PREGAIN_CH_CONTROLS(x, 3)
#define ATUNE_SPUM_POSTGAIN_CH_CONTROLS(x, ch) \
SOC_SINGLE_S_TLV("SPUM"#x" POSTGAIN CH"#ch" Main Volume", \
ATUNE_SPUM_DSGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_SHIFT_L(ch), \
-32, 20, 5, 0, atune_gain_shift_tlv), \
SOC_SINGLE_S_TLV("SPUM"#x" POSTGAIN CH"#ch" Fine Volume", \
ATUNE_SPUM_DSGAIN_GAIN_CH(x, ch), \
ATUNE_CH_GAIN_INDEX_L(ch), \
0, 5, 2, 0, atune_gain_index_tlv)
#define ATUNE_SPUM_POSTGAIN_CONTROLS(x) \
ATUNE_SPUM_POSTGAIN_CH_CONTROLS(x, 0), \
ATUNE_SPUM_POSTGAIN_CH_CONTROLS(x, 1), \
ATUNE_SPUM_POSTGAIN_CH_CONTROLS(x, 2), \
ATUNE_SPUM_POSTGAIN_CH_CONTROLS(x, 3)
static int atune_param_update_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = 0;
return 0;
}
static int atune_param_update_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int shift = mc->shift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int val, val_mask;
int err;
val = (ucontrol->value.integer.value[0] & mask) << shift;
val_mask = mask << shift;
/* param_update field is write only but r/w field is in same SFR.
* To ensure write, write 0 first and then write requested value.
*/
err = snd_soc_component_update_bits(component, reg, val_mask, 0);
if (err < 0 || val == 0)
return err;
return snd_soc_component_update_bits(component, reg, val_mask, val);
}
static const unsigned int headroom_mask = ATUNE_HEADROOM_HPF_MASK >>
ATUNE_HEADROOM_HPF_L;
static const char * const headroom_texts[] = {
"6dB", "12dB", "18dB", "24dB",
};
static const unsigned int headroom_values[] = {
2, 3, 4, 5,
};
static const unsigned int headroom_items = ARRAY_SIZE(headroom_texts);
#define ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(x, ch) \
SOC_VALUE_ENUM_SINGLE(ATUNE_SPUS_BQF_CH##ch##_HEADROOM(x), \
ATUNE_HEADROOM_HPF_L, headroom_mask, \
headroom_items, headroom_texts, headroom_values)
static const struct soc_enum spus_bqf_ch_hpf_headroom[][COUNT_CH] = {
/* SPUS BQF0 */
{
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 0),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 1),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 2),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 3),
},
/* SPUS BQF1 */
{
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 0),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 1),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 2),
ATUNE_SPUS_BQF_CH_HPF_HEADROOM_ENUM(0, 3),
},
};
#define ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, eq) \
SOC_VALUE_ENUM_SINGLE(ATUNE_SPUS_BQF_CH##ch##_HEADROOM(x), \
ATUNE_HEADROOM_EQ_L(eq), headroom_mask, \
headroom_items, headroom_texts, headroom_values)
#define ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(x, ch) \
ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 0), \
ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 1), \
ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 2), \
ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 3), \
ATUNE_SPUS_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 4)
static const struct soc_enum spus_bqf_ch_eq_headroom[][COUNT_CH][COUNT_EQ] = {
/* SPUS0 */
{
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(0, 0) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(0, 1) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(0, 2) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(0, 3) },
},
/* SPUS1 */
{
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(1, 0) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(1, 1) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(1, 2) },
{ ATUNE_SPUS_BQF_CH_HEADROOM_ENUM(1, 3) },
},
};
#define ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(x, ch) \
SOC_VALUE_ENUM_SINGLE(ATUNE_SPUM_BQF_CH##ch##_HEADROOM(x), \
ATUNE_HEADROOM_HPF_L, headroom_mask, \
headroom_items, headroom_texts, headroom_values)
static const struct soc_enum spum_bqf_ch_hpf_headroom[][COUNT_CH] = {
/* SPUM0 */
{
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 0),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 1),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 2),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 3),
},
/* SPUM1 */
{
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 0),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 1),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 2),
ATUNE_SPUM_BQF_CH_HPF_HEADROOM_ENUM(0, 3),
},
};
#define ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, eq) \
SOC_VALUE_ENUM_SINGLE(ATUNE_SPUM_BQF_CH##ch##_HEADROOM(x), \
ATUNE_HEADROOM_EQ_L(eq), headroom_mask, \
headroom_items, headroom_texts, headroom_values)
#define ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(x, ch) \
ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 0), \
ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 1), \
ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 2), \
ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 3), \
ATUNE_SPUM_BQF_CH_EQ_HEADROOM_ENUM(x, ch, 4)
static const struct soc_enum spum_bqf_ch_eq_headroom[][COUNT_CH][COUNT_EQ] = {
/* SPUM0 */
{
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(0, 0) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(0, 1) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(0, 2) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(0, 3) },
},
/* SPUM1 */
{
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(1, 0) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(1, 1) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(1, 2) },
{ ATUNE_SPUM_BQF_CH_HEADROOM_ENUM(1, 3) },
},
};
#define ATUNE_SPUS_BQF_CH_HEADROOM_CONTROLS(x, ch) \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM HPF", \
spus_bqf_ch_hpf_headroom[x][ch]), \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM EQ0", \
spus_bqf_ch_eq_headroom[x][ch][0]), \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM EQ1", \
spus_bqf_ch_eq_headroom[x][ch][1]), \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM EQ2", \
spus_bqf_ch_eq_headroom[x][ch][2]), \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM EQ3", \
spus_bqf_ch_eq_headroom[x][ch][3]), \
SOC_ENUM("SPUS"#x" CH"#ch" HEADROOM EQ4", \
spus_bqf_ch_eq_headroom[x][ch][4])
#define ATUNE_SPUS_BQF_HEADROOM_CONTROLS(x) \
ATUNE_SPUS_BQF_CH_HEADROOM_CONTROLS(x, 0), \
ATUNE_SPUS_BQF_CH_HEADROOM_CONTROLS(x, 1), \
ATUNE_SPUS_BQF_CH_HEADROOM_CONTROLS(x, 2), \
ATUNE_SPUS_BQF_CH_HEADROOM_CONTROLS(x, 3)
#define ATUNE_SPUM_BQF_CH_HEADROOM_CONTROLS(x, ch) \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM HPF", \
spum_bqf_ch_hpf_headroom[x][ch]), \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM EQ0", \
spum_bqf_ch_eq_headroom[x][ch][0]), \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM EQ1", \
spum_bqf_ch_eq_headroom[x][ch][1]), \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM EQ2", \
spum_bqf_ch_eq_headroom[x][ch][2]), \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM EQ3", \
spum_bqf_ch_eq_headroom[x][ch][3]), \
SOC_ENUM("SPUM"#x" CH"#ch" HEADROOM EQ4", \
spum_bqf_ch_eq_headroom[x][ch][4])
#define ATUNE_SPUM_BQF_HEADROOM_CONTROLS(x) \
ATUNE_SPUM_BQF_CH_HEADROOM_CONTROLS(x, 0), \
ATUNE_SPUM_BQF_CH_HEADROOM_CONTROLS(x, 1), \
ATUNE_SPUM_BQF_CH_HEADROOM_CONTROLS(x, 2), \
ATUNE_SPUM_BQF_CH_HEADROOM_CONTROLS(x, 3)
#define ATUNE_SPUS_BQF_CH_POSTAMP_CONTROLS(x, ch) \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP HPF", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_HPF_L, 3, 0), \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP EQ0", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(0), 3, 0), \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP EQ1", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(1), 3, 0), \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP EQ2", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(2), 3, 0), \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP EQ3", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(3), 3, 0), \
SOC_SINGLE("SPUS"#x" CH"#ch" POSTAMP EQ4", \
ATUNE_SPUS_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(4), 3, 0)
#define ATUNE_SPUS_BQF_POSTAMP_CONTROLS(x) \
ATUNE_SPUS_BQF_CH_POSTAMP_CONTROLS(x, 0), \
ATUNE_SPUS_BQF_CH_POSTAMP_CONTROLS(x, 1), \
ATUNE_SPUS_BQF_CH_POSTAMP_CONTROLS(x, 2), \
ATUNE_SPUS_BQF_CH_POSTAMP_CONTROLS(x, 3)
#define ATUNE_SPUM_BQF_CH_POSTAMP_CONTROLS(x, ch) \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP HPF", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_HPF_L, 3, 0), \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP EQ0", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(0), 3, 0), \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP EQ1", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(1), 3, 0), \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP EQ2", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(2), 3, 0), \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP EQ3", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(3), 3, 0), \
SOC_SINGLE("SPUM"#x" CH"#ch" POSTAMP EQ4", \
ATUNE_SPUM_BQF_CH##ch##_POSTAMP(x), \
ATUNE_POSTAMP_EQ_L(4), 3, 0)
#define ATUNE_SPUM_BQF_POSTAMP_CONTROLS(x) \
ATUNE_SPUM_BQF_CH_POSTAMP_CONTROLS(x, 0), \
ATUNE_SPUM_BQF_CH_POSTAMP_CONTROLS(x, 1), \
ATUNE_SPUM_BQF_CH_POSTAMP_CONTROLS(x, 2), \
ATUNE_SPUM_BQF_CH_POSTAMP_CONTROLS(x, 3)
struct atune_multi_control {
int min, max;
int regs[8];
unsigned int shifts[8];
unsigned int count;
unsigned int sign_bit;
unsigned int invert:1;
unsigned int autodisable:1;
struct snd_soc_dobj dobj;
};
/* revisit snd_soc_read_signed() in ASoC */
static int cmpnt_read_signed(struct snd_soc_component *component,
unsigned int reg, unsigned int mask, unsigned int shift,
unsigned int sign_bit, int *signed_val)
{
unsigned int val;
val = snd_soc_component_read(component, reg);
val = (val >> shift) & mask;
if (!sign_bit || !(val & BIT(sign_bit)))
*signed_val = val;
else
*signed_val = (int)val | ~((int)(BIT(sign_bit) - 1));
return 0;
}
static int atune_info_multi(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct atune_multi_control *amc =
(struct atune_multi_control *)kcontrol->private_value;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = amc->count;
uinfo->value.integer.min = amc->min;
uinfo->value.integer.max = amc->max;
return 0;
}
static int __maybe_unused atune_get_multi(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct atune_multi_control *amc =
(struct atune_multi_control *)kcontrol->private_value;
unsigned int *reg = amc->regs;
unsigned int *shift = amc->shifts;
unsigned int i, count = amc->count;
int max = amc->max;
int sign_bit = amc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = amc->invert;
int val;
int ret;
if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
for (i = count - 1; i; i--) {
ret = cmpnt_read_signed(component, reg[i], mask, shift[i],
sign_bit, &val);
if (ret)
return ret;
ucontrol->value.integer.value[i] = invert ? (max - val): val;
}
return 0;
}
static int __maybe_unused atune_put_multi(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct atune_multi_control *amc =
(struct atune_multi_control *)kcontrol->private_value;
unsigned int *reg = amc->regs;
unsigned int *shift = amc->shifts;
unsigned int i, count = amc->count;
int max = amc->max;
unsigned int sign_bit = amc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = amc->invert;
int err;
unsigned int val, val_mask;
if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
for (i = count - 1; i; i--) {
val = ((ucontrol->value.integer.value[i]) & mask);
if (invert)
val = max - val;
val_mask = mask << shift[i];
val = val << shift[i];
err = snd_soc_component_update_bits(component, reg[i],
val_mask, val);
if (err < 0)
break;
}
return err;
}
static int atune_get_multi_linear(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct atune_multi_control *amc =
(struct atune_multi_control *)kcontrol->private_value;
unsigned int reg = amc->regs[0];
unsigned int shift = amc->shifts[0];
unsigned int offset;
unsigned int i, count = amc->count;
int max = amc->max;
int sign_bit = amc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = amc->invert;
int val;
int ret;
if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
for (i = 0, offset = 0; i < count; i++, offset += SFR_STRIDE) {
ret = cmpnt_read_signed(component, reg + offset, mask, shift,
sign_bit, &val);
if (ret)
return ret;
ucontrol->value.integer.value[i] = invert ? (max - val): val;
}
return 0;
}
static int atune_put_multi_linear(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct atune_multi_control *amc =
(struct atune_multi_control *)kcontrol->private_value;
unsigned int reg = amc->regs[0];
unsigned int shift = amc->shifts[0];
unsigned int offset;
unsigned int i, count = amc->count;
int max = amc->max;
unsigned int sign_bit = amc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = amc->invert;
int err;
unsigned int val, val_mask;
if (sign_bit)
mask = BIT(sign_bit + 1) - 1;
for (i = 0, offset = 0; i < count; i++, offset += SFR_STRIDE) {
val = ((ucontrol->value.integer.value[i]) & mask);
if (invert)
val = max - val;
val_mask = mask << shift;
val = val << shift;
err = snd_soc_component_update_bits(component, reg + offset,
val_mask, val);
if (err < 0)
break;
}
return err;
}
#define ATUNE_MULTI_VALUE(xregs, xshifts, xcount, xmin, xmax, \
xsign_bit, xinvert) \
((unsigned long)&(struct atune_multi_control) \
{.regs = xregs, .shifts = xshifts, .count = xcount, .min = xmin, \
.max = xmax, .sign_bit = xsign_bit, .invert = xinvert,})
#define ATUNE_MULTI(xname, regs, shifts, min, max, sign_bit, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = atune_info_multi, .get = atune_get_multi,\
.put = atune_put_multi, \
.private_value = ATUNE_MULTI_VALUE(regs, shifts, \
ARRAY_SIZE(regs), min, max, sign_bit, invert) }
#define ATUNE_MULTI_LINEAR(xname, regbase, shift, count, min, max, \
sign_bit, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = atune_info_multi, .get = atune_get_multi_linear,\
.put = atune_put_multi_linear, \
.private_value = ATUNE_MULTI_VALUE({ regbase }, { shift }, \
count, min, max, sign_bit, invert) }
#define ATUNE_SPUS_BQF_CH_COEF_CONTROLS(x, ch) \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" HPF COEF", \
ATUNE_SPUS_BQF_CH##ch##_HPF_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" EQ0 COEF", \
ATUNE_SPUS_BQF_CH##ch##_EQ0_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" EQ1 COEF", \
ATUNE_SPUS_BQF_CH##ch##_EQ1_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" EQ2 COEF", \
ATUNE_SPUS_BQF_CH##ch##_EQ2_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" EQ3 COEF", \
ATUNE_SPUS_BQF_CH##ch##_EQ3_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUS"#x" CH"#ch" EQ4 COEF", \
ATUNE_SPUS_BQF_CH##ch##_EQ4_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0)
#define ATUNE_SPUS_BQF_COEF_CONTROLS(x) \
ATUNE_SPUS_BQF_CH_COEF_CONTROLS(x, 0), \
ATUNE_SPUS_BQF_CH_COEF_CONTROLS(x, 1), \
ATUNE_SPUS_BQF_CH_COEF_CONTROLS(x, 2), \
ATUNE_SPUS_BQF_CH_COEF_CONTROLS(x, 3)
#define ATUNE_SPUM_BQF_CH_COEF_CONTROLS(x, ch) \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" HPF COEF", \
ATUNE_SPUM_BQF_CH##ch##_HPF_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" EQ0 COEF", \
ATUNE_SPUM_BQF_CH##ch##_EQ0_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" EQ1 COEF", \
ATUNE_SPUM_BQF_CH##ch##_EQ1_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" EQ2 COEF", \
ATUNE_SPUM_BQF_CH##ch##_EQ2_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" EQ3 COEF", \
ATUNE_SPUM_BQF_CH##ch##_EQ3_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0), \
ATUNE_MULTI_LINEAR("SPUM"#x" CH"#ch" EQ4 COEF", \
ATUNE_SPUM_BQF_CH##ch##_EQ4_COEF0(x), \
ATUNE_COEF_L, 5, INT_MIN, INT_MAX, 31, 0)
#define ATUNE_SPUM_BQF_COEF_CONTROLS(x) \
ATUNE_SPUM_BQF_CH_COEF_CONTROLS(x, 0), \
ATUNE_SPUM_BQF_CH_COEF_CONTROLS(x, 1), \
ATUNE_SPUM_BQF_CH_COEF_CONTROLS(x, 2), \
ATUNE_SPUM_BQF_CH_COEF_CONTROLS(x, 3)
static const DECLARE_TLV_DB_SCALE(atune_ng_threshold_tlv, -9600, 100, 0);
static const DECLARE_TLV_DB_MINMAX(atune_drc_makeup_gain_tlv, 0, 3000);
static const DECLARE_TLV_DB_SCALE(atune_drc_threshold_tlv, -8000, 100, 0);
#define ATUNE_SPUS_DRC_BAND_CONTROLS(x, band) \
SOC_SINGLE_S_TLV("SPUS"#x" DRC "#band" MAKEUP GAIN", \
ATUNE_SPUS_DRC_COMP_##band##0(x), \
ATUNE_MAKEUP_GAIN_L, 0x0400, 0x7FFF, \
15, 0, atune_drc_makeup_gain_tlv), \
SOC_SINGLE_S_TLV("SPUS"#x" DRC "#band" THRESHOLD", \
ATUNE_SPUS_DRC_COMP_##band##0(x), \
ATUNE_THRS_L, -80, 0, 7, 0, \
atune_drc_threshold_tlv), \
SOC_SINGLE("SPUS"#x" DRC "#band" RATIO", \
ATUNE_SPUS_DRC_COMP_##band##0(x), \
ATUNE_RATIO_L, 0xf, 0), \
SOC_SINGLE("SPUS"#x" DRC "#band" RMS", \
ATUNE_SPUS_DRC_COMP_##band##0(x), \
ATUNE_RMS_ENABLE_L, 1, 0), \
SOC_SINGLE("SPUS"#x" DRC "#band" MUTE", \
ATUNE_SPUS_DRC_COMP_##band##0(x), \
ATUNE_MUTE_ENABLE_L, 1, 0), \
SOC_SINGLE("SPUS"#x" DRC "#band" ATTACK", \
ATUNE_SPUS_DRC_COMP_##band##1(x), \
ATUNE_ATTACK_TIME_L, INT_MAX, 0), \
SOC_SINGLE("SPUS"#x" DRC "#band" RELEASE", \
ATUNE_SPUS_DRC_COMP_##band##2(x), \
ATUNE_RELEASE_TIME_L, INT_MAX, 0)
#define ATUNE_SPUS_DRC_CONTROLS(x) \
ATUNE_SPUS_DRC_BAND_CONTROLS(x, LB), \
ATUNE_SPUS_DRC_BAND_CONTROLS(x, MB), \
ATUNE_SPUS_DRC_BAND_CONTROLS(x, HB)
#define ATUNE_SPUM_DRC_BAND_CONTROLS(x, band) \
SOC_SINGLE_S_TLV("SPUM"#x" DRC "#band" MAKEUP GAIN", \
ATUNE_SPUM_DRC_COMP_##band##0(x), \
ATUNE_MAKEUP_GAIN_L, 0x0400, 0x7FFF, \
15, 0, atune_drc_makeup_gain_tlv), \
SOC_SINGLE_S_TLV("SPUM"#x" DRC "#band" THRESHOLD", \
ATUNE_SPUM_DRC_COMP_##band##0(x), \
ATUNE_THRS_L, -80, 0, 7, 0, \
atune_drc_threshold_tlv), \
SOC_SINGLE("SPUM"#x" DRC "#band" RATIO", \
ATUNE_SPUM_DRC_COMP_##band##0(x), \
ATUNE_RATIO_L, 0xf, 0), \
SOC_SINGLE("SPUM"#x" DRC "#band" RMS", \
ATUNE_SPUM_DRC_COMP_##band##0(x), \
ATUNE_RMS_ENABLE_L, 1, 0), \
SOC_SINGLE("SPUM"#x" DRC "#band" MUTE", \
ATUNE_SPUM_DRC_COMP_##band##0(x), \
ATUNE_MUTE_ENABLE_L, 1, 0), \
SOC_SINGLE("SPUM"#x" DRC "#band" ATTACK", \
ATUNE_SPUM_DRC_COMP_##band##1(x), \
ATUNE_ATTACK_TIME_L, INT_MAX, 0), \
SOC_SINGLE("SPUM"#x" DRC "#band" RELEASE", \
ATUNE_SPUM_DRC_COMP_##band##2(x), \
ATUNE_RELEASE_TIME_L, INT_MAX, 0)
#define ATUNE_SPUM_DRC_CONTROLS(x) \
ATUNE_SPUM_DRC_BAND_CONTROLS(x, LB), \
ATUNE_SPUM_DRC_BAND_CONTROLS(x, MB), \
ATUNE_SPUM_DRC_BAND_CONTROLS(x, HB)
static const struct snd_kcontrol_new atune_controls[] = {
SOC_ENUM("SPUS0 PREGAIN FUNC", spus0_pregain_func_enum),
SOC_SINGLE("SPUS0 PREGAIN EN", ATUNE_SPUS_USGAIN_CTRL(0),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUS0 PREGAIN VOL CHANGE FADE IN",
ATUNE_SPUS_USGAIN_VOL_CHANGE_FIN(0),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUS0 PREGAIN VOL CHANGE FADE OUT",
ATUNE_SPUS_USGAIN_VOL_CHANGE_FOUT(0),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUS_PREGAIN_CONTROLS(0),
SOC_SINGLE("SPUS0 EQ EN", ATUNE_SPUS_BQF_CTRL(0),
ATUNE_EQ_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS0 HPF EN", ATUNE_SPUS_BQF_CTRL(0),
ATUNE_HPF_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS0 CASCADE EN", ATUNE_SPUS_BQF_CTRL(0),
ATUNE_CASCADE_EN_L, 1, 0),
SOC_SINGLE_EXT("SPUS0 PARAM UPDATE", ATUNE_SPUS_BQF_CTRL(0),
ATUNE_PARAM_UPDATE_L, 1, 0,
atune_param_update_get, atune_param_update_put),
ATUNE_SPUS_BQF_HEADROOM_CONTROLS(0),
ATUNE_SPUS_BQF_POSTAMP_CONTROLS(0),
ATUNE_SPUS_BQF_COEF_CONTROLS(0),
SOC_SINGLE("SPUS0 LIMITER WINDOW", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_LIMIT_WINDOW_SIZE_L, 0xff, 0),
SOC_SINGLE_S_TLV("SPUS0 DRC NG THRESHOLD", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_NOISE_THRS_L, -108, -12, 7, 0,
atune_ng_threshold_tlv),
SOC_SINGLE("SPUS0 DRC NG HB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUS0 DRC NG MB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUS0 DRC NG LB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUS0 DRC HB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUS0 DRC MB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUS0 DRC LB EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUS0 LIMITER EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_LIMIT_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS0 DRC EN", ATUNE_SPUS_DRC_CTRL(0),
ATUNE_DRC_ENABLE_L, 1, 0),
ATUNE_SPUS_DRC_CONTROLS(0),
SOC_SINGLE("SPUS0 LIMITER THRESHOLD", ATUNE_SPUS_DRC_LMT_CTRL0(0),
ATUNE_THRESHOLD_L, INT_MAX, 0),
SOC_SINGLE("SPUS0 LIMITER ATTACK", ATUNE_SPUS_DRC_LMT_CTRL1(0),
ATUNE_ATTACK_TIME_L, INT_MAX, 0),
ATUNE_MULTI_LINEAR("SPUS0 DRC XPF0 COEF", ATUNE_SPUS_DRC_xPF0_COEF0(0),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
ATUNE_MULTI_LINEAR("SPUS0 DRC XPF1 COEF", ATUNE_SPUS_DRC_xPF1_COEF0(0),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
SOC_ENUM("SPUS0 POSTGAIN FUNC", spus0_postgain_func_enum),
SOC_SINGLE("SPUS0 POSTGAIN EN", ATUNE_SPUS_DSGAIN_CTRL(0),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUS0 POSTGAIN VOL CHANGE FADE IN",
ATUNE_SPUS_DSGAIN_VOL_CHANGE_FIN(0),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUS0 POSTGAIN VOL CHANGE FADE OUT",
ATUNE_SPUS_DSGAIN_VOL_CHANGE_FOUT(0),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUS_POSTGAIN_CONTROLS(0),
SOC_ENUM("SPUS0 POSTGAIN Dither Type", spus0_postgain_dither_type_enum),
SOC_ENUM("SPUM0 PREGAIN FUNC", spum0_pregain_func_enum),
SOC_SINGLE("SPUM0 PREGAIN EN", ATUNE_SPUM_USGAIN_CTRL(0),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUM0 PREGAIN VOL CHANGE FADE IN",
ATUNE_SPUM_USGAIN_VOL_CHANGE_FIN(0),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUM0 PREGAIN VOL CHANGE FADE OUT",
ATUNE_SPUM_USGAIN_VOL_CHANGE_FOUT(0),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUM_PREGAIN_CONTROLS(0),
SOC_SINGLE("SPUM0 EQ EN", ATUNE_SPUM_BQF_CTRL(0),
ATUNE_EQ_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM0 HPF EN", ATUNE_SPUM_BQF_CTRL(0),
ATUNE_HPF_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM0 CASCADE EN", ATUNE_SPUM_BQF_CTRL(0),
ATUNE_CASCADE_EN_L, 1, 0),
SOC_SINGLE_EXT("SPUM0 PARAM UPDATE", ATUNE_SPUM_BQF_CTRL(0),
ATUNE_PARAM_UPDATE_L, 1, 0,
atune_param_update_get, atune_param_update_put),
ATUNE_SPUM_BQF_HEADROOM_CONTROLS(0),
ATUNE_SPUM_BQF_POSTAMP_CONTROLS(0),
ATUNE_SPUM_BQF_COEF_CONTROLS(0),
SOC_SINGLE("SPUM0 LIMITER WINDOW", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_LIMIT_WINDOW_SIZE_L, 0xff, 0),
SOC_SINGLE_S_TLV("SPUM0 DRC NG THRESHOLD", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_NOISE_THRS_L, -108, -12, 7, 0,
atune_ng_threshold_tlv),
SOC_SINGLE("SPUM0 DRC NG HB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUM0 DRC NG MB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUM0 DRC NG LB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_NG_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUM0 DRC HB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUM0 DRC MB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUM0 DRC LB EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUM0 LIMITER EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_LIMIT_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM0 DRC EN", ATUNE_SPUM_DRC_CTRL(0),
ATUNE_DRC_ENABLE_L, 1, 0),
ATUNE_SPUM_DRC_CONTROLS(0),
SOC_SINGLE("SPUM0 LIMITER THRESHOLD", ATUNE_SPUM_DRC_LMT_CTRL0(0),
ATUNE_THRESHOLD_L, INT_MAX, 0),
SOC_SINGLE("SPUM0 LIMITER ATTACK", ATUNE_SPUM_DRC_LMT_CTRL1(0),
ATUNE_ATTACK_TIME_L, INT_MAX, 0),
ATUNE_MULTI_LINEAR("SPUM0 DRC XPF0 COEF", ATUNE_SPUM_DRC_xPF0_COEF0(0),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
ATUNE_MULTI_LINEAR("SPUM0 DRC XPF1 COEF", ATUNE_SPUM_DRC_xPF1_COEF0(0),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
SOC_ENUM("SPUM0 POSTGAIN FUNC", spum0_postgain_func_enum),
SOC_SINGLE("SPUM0 POSTGAIN EN", ATUNE_SPUM_DSGAIN_CTRL(0),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUM0 POSTGAIN VOL CHANGE FADE IN",
ATUNE_SPUM_DSGAIN_VOL_CHANGE_FIN(0),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUM0 POSTGAIN VOL CHANGE FADE OUT",
ATUNE_SPUM_DSGAIN_VOL_CHANGE_FOUT(0),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUM_POSTGAIN_CONTROLS(0),
SOC_ENUM("SPUM0 POSTGAIN Dither Type", spum0_postgain_dither_type_enum),
};
static const struct snd_kcontrol_new atune1_controls[] = {
SOC_ENUM("SPUS1 PREGAIN FUNC", spus1_pregain_func_enum),
SOC_SINGLE("SPUS1 PREGAIN EN", ATUNE_SPUS_USGAIN_CTRL(1),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUS1 PREGAIN VOL CHANGE FADE IN",
ATUNE_SPUS_USGAIN_VOL_CHANGE_FIN(1),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUS1 PREGAIN VOL CHANGE FADE OUT",
ATUNE_SPUS_USGAIN_VOL_CHANGE_FOUT(1),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUS_PREGAIN_CONTROLS(1),
SOC_SINGLE("SPUS1 EQ EN", ATUNE_SPUS_BQF_CTRL(1),
ATUNE_EQ_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS1 HPF EN", ATUNE_SPUS_BQF_CTRL(1),
ATUNE_HPF_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS1 CASCADE EN", ATUNE_SPUS_BQF_CTRL(1),
ATUNE_CASCADE_EN_L, 1, 0),
SOC_SINGLE_EXT("SPUS1 PARAM UPDATE", ATUNE_SPUS_BQF_CTRL(1),
ATUNE_PARAM_UPDATE_L, 1, 0,
atune_param_update_get, atune_param_update_put),
ATUNE_SPUS_BQF_HEADROOM_CONTROLS(1),
ATUNE_SPUS_BQF_POSTAMP_CONTROLS(1),
ATUNE_SPUS_BQF_COEF_CONTROLS(1),
SOC_SINGLE("SPUS1 LIMITER WINDOW", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_LIMIT_WINDOW_SIZE_L, 0xff, 0),
SOC_SINGLE_S_TLV("SPUS1 DRC NG THRESHOLD", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_NOISE_THRS_L, -108, -12, 7, 0,
atune_ng_threshold_tlv),
SOC_SINGLE("SPUS1 DRC NG HB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUS1 DRC NG MB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUS1 DRC NG LB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUS1 DRC HB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUS1 DRC MB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUS1 DRC LB EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUS1 LIMITER EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_LIMIT_ENABLE_L, 1, 0),
SOC_SINGLE("SPUS1 DRC EN", ATUNE_SPUS_DRC_CTRL(1),
ATUNE_DRC_ENABLE_L, 1, 0),
ATUNE_SPUS_DRC_CONTROLS(1),
SOC_SINGLE("SPUS1 LIMITER THRESHOLD", ATUNE_SPUS_DRC_LMT_CTRL0(1),
ATUNE_THRESHOLD_L, INT_MAX, 0),
SOC_SINGLE("SPUS1 LIMITER ATTACK", ATUNE_SPUS_DRC_LMT_CTRL1(1),
ATUNE_ATTACK_TIME_L, INT_MAX, 0),
ATUNE_MULTI_LINEAR("SPUS1 DRC XPF0 COEF", ATUNE_SPUS_DRC_xPF0_COEF0(1),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
ATUNE_MULTI_LINEAR("SPUS1 DRC XPF1 COEF", ATUNE_SPUS_DRC_xPF1_COEF0(1),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
SOC_ENUM("SPUS1 POSTGAIN FUNC", spus1_postgain_func_enum),
SOC_SINGLE("SPUS1 POSTGAIN EN", ATUNE_SPUS_DSGAIN_CTRL(1),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUS1 POSTGAIN VOL CHANGE FADE IN",
ATUNE_SPUS_DSGAIN_VOL_CHANGE_FIN(1),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUS1 POSTGAIN VOL CHANGE FADE OUT",
ATUNE_SPUS_DSGAIN_VOL_CHANGE_FOUT(1),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUS_POSTGAIN_CONTROLS(1),
SOC_ENUM("SPUS1 POSTGAIN Dither Type", spus1_postgain_dither_type_enum),
SOC_ENUM("SPUM1 PREGAIN FUNC", spum1_pregain_func_enum),
SOC_SINGLE("SPUM1 PREGAIN EN", ATUNE_SPUM_USGAIN_CTRL(1),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUM1 PREGAIN VOL CHANGE FADE IN",
ATUNE_SPUM_USGAIN_VOL_CHANGE_FIN(1),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUM1 PREGAIN VOL CHANGE FADE OUT",
ATUNE_SPUM_USGAIN_VOL_CHANGE_FOUT(1),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUM_PREGAIN_CONTROLS(1),
SOC_SINGLE("SPUM1 EQ EN", ATUNE_SPUM_BQF_CTRL(1),
ATUNE_EQ_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM1 HPF EN", ATUNE_SPUM_BQF_CTRL(1),
ATUNE_HPF_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM1 CASCADE EN", ATUNE_SPUM_BQF_CTRL(1),
ATUNE_CASCADE_EN_L, 1, 0),
SOC_SINGLE_EXT("SPUM1 PARAM UPDATE", ATUNE_SPUM_BQF_CTRL(1),
ATUNE_PARAM_UPDATE_L, 1, 0,
atune_param_update_get, atune_param_update_put),
ATUNE_SPUM_BQF_HEADROOM_CONTROLS(1),
ATUNE_SPUM_BQF_POSTAMP_CONTROLS(1),
ATUNE_SPUM_BQF_COEF_CONTROLS(1),
SOC_SINGLE("SPUM1 LIMITER WINDOW", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_LIMIT_WINDOW_SIZE_L, 0xff, 0),
SOC_SINGLE_S_TLV("SPUM1 DRC NG THRESHOLD", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_NOISE_THRS_L, -108, -12, 7, 0,
atune_ng_threshold_tlv),
SOC_SINGLE("SPUM1 DRC NG HB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUM1 DRC NG MB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUM1 DRC NG LB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_NG_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUM1 DRC HB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_ENABLE_HB_L, 1, 0),
SOC_SINGLE("SPUM1 DRC MB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_ENABLE_MB_L, 1, 0),
SOC_SINGLE("SPUM1 DRC LB EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_ENABLE_LB_L, 1, 0),
SOC_SINGLE("SPUM1 LIMITER EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_LIMIT_ENABLE_L, 1, 0),
SOC_SINGLE("SPUM1 DRC EN", ATUNE_SPUM_DRC_CTRL(1),
ATUNE_DRC_ENABLE_L, 1, 0),
ATUNE_SPUM_DRC_CONTROLS(1),
SOC_SINGLE("SPUM1 LIMITER THRESHOLD", ATUNE_SPUM_DRC_LMT_CTRL0(1),
ATUNE_THRESHOLD_L, INT_MAX, 0),
SOC_SINGLE("SPUM1 LIMITER ATTACK", ATUNE_SPUM_DRC_LMT_CTRL1(1),
ATUNE_ATTACK_TIME_L, INT_MAX, 0),
ATUNE_MULTI_LINEAR("SPUM1 DRC XPF0 COEF", ATUNE_SPUM_DRC_xPF0_COEF0(1),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
ATUNE_MULTI_LINEAR("SPUM1 DRC XPF1 COEF", ATUNE_SPUM_DRC_xPF1_COEF0(1),
ATUNE_COEF_L, 4, INT_MIN, INT_MAX, 31, 0),
SOC_ENUM("SPUM1 POSTGAIN FUNC", spum1_postgain_func_enum),
SOC_SINGLE("SPUM1 POSTGAIN EN", ATUNE_SPUM_DSGAIN_CTRL(1),
ATUNE_ENABLE_L, 1, 0),
SOC_SINGLE_XR_SX("SPUM1 POSTGAIN VOL CHANGE FADE IN",
ATUNE_SPUM_DSGAIN_VOL_CHANGE_FIN(1),
1, 32, 0, INT_MAX, 0),
SOC_SINGLE_XR_SX("SPUM1 POSTGAIN VOL CHANGE FADE OUT",
ATUNE_SPUM_DSGAIN_VOL_CHANGE_FOUT(1),
1, 32, INT_MIN, 0, 0),
ATUNE_SPUM_POSTGAIN_CONTROLS(1),
SOC_ENUM("SPUM1 POSTGAIN Dither Type", spum1_postgain_dither_type_enum),
};
static const unsigned int spus_pre_tune_mask =
ABOX_PRE_TUNE_SEL_MASK(0) >> ABOX_PRE_TUNE_SEL_L(0);
static const char * const spus_pre_tune_texts[] = {
"SPUS0", "SPUS1", "SPUS2", "SPUS3",
"SPUS4", "SPUS5", "SPUS6", "SPUS7",
"SPUS8", "SPUS9", "SPUS10", "SPUS11",
"RESERVED",
};
static const unsigned int spus_pre_tune_values[] = {
0x0, 0x1, 0x2, 0x3,
0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb,
0xf,
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_pre_tune0_enum,
ABOX_SPUS_CTRL_TUNE_SEL, ABOX_PRE_TUNE_SEL_L(0),
spus_pre_tune_mask, spus_pre_tune_texts, spus_pre_tune_values);
static const struct snd_kcontrol_new spus_pre_tune0_controls[] = {
SOC_DAPM_ENUM("SPUS PRETUNE0 SEL", spus_pre_tune0_enum),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_pre_tune1_enum,
ABOX_SPUS_CTRL_TUNE_SEL, ABOX_PRE_TUNE_SEL_L(1),
spus_pre_tune_mask, spus_pre_tune_texts, spus_pre_tune_values);
static const struct snd_kcontrol_new spus_pre_tune1_controls[] = {
SOC_DAPM_ENUM("SPUS PRETUNE1 SEL", spus_pre_tune1_enum),
};
static int atune_find_spus(struct snd_soc_component *cmpnt, int aid)
{
unsigned int val;
int ret;
val = snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_TUNE_SEL);
ret = (val & ABOX_PRE_TUNE_SEL_MASK(aid)) >> ABOX_PRE_TUNE_SEL_L(aid);
if (ret > 0xb)
ret = -EPIPE;
return ret;
}
static const unsigned int spus_post_tune_mask =
ABOX_POST_TUNE_SEL_MASK(0) >> ABOX_POST_TUNE_SEL_L(0);
static const char * const spus_post_tune_texts[] = {
"SIFS0", "SIFS1", "SIFS2", "SIFS3",
"SIFS4", "SIFS5", "SIFS6", "RESERVED",
};
static const unsigned int spus_post_tune_values[] = {
0x0, 0x1, 0x2, 0x3,
0x4, 0x5, 0x6, 0xf,
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_post_tune0_enum,
ABOX_SPUS_CTRL_TUNE_SEL, ABOX_POST_TUNE_SEL_L(0),
spus_post_tune_mask, spus_post_tune_texts,
spus_post_tune_values);
static const struct snd_kcontrol_new spus_post_tune0_controls[] = {
SOC_DAPM_ENUM("SPUS POSTTUNE0 SEL", spus_post_tune0_enum),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_post_tune1_enum,
ABOX_SPUS_CTRL_TUNE_SEL, ABOX_POST_TUNE_SEL_L(1),
spus_post_tune_mask, spus_post_tune_texts,
spus_post_tune_values);
static const struct snd_kcontrol_new spus_post_tune1_controls[] = {
SOC_DAPM_ENUM("SPUS POSTTUNE1 SEL", spus_post_tune1_enum),
};
static int atune_find_sifs(struct snd_soc_component *cmpnt, int aid)
{
unsigned int val;
int ret;
val = snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_TUNE_SEL);
ret = (val & ABOX_POST_TUNE_SEL_MASK(aid)) >> ABOX_POST_TUNE_SEL_L(aid);
if (ret > 0x6)
ret = -EPIPE;
return ret;
}
static const unsigned int spum_tune_mask =
ABOX_PRE_TUNE_SEL_MASK(0) >> ABOX_PRE_TUNE_SEL_L(0);
static const char * const spum_tune_texts[] = {
"SIFM0", "SIFM1", "SIFM2", "SIFM3",
"SIFM4", "SIFM5", "SIFM6", "SIFM7",
"SIFM8", "SIFM9", "SIFM10", "SIFM11",
"RESERVED",
};
static const unsigned int spum_tune_values[] = {
0x0, 0x1, 0x2, 0x3,
0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb,
0xf,
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_pre_tune0_enum,
ABOX_SPUM_CTRL_TUNE_SEL, ABOX_PRE_TUNE_SEL_L(0),
spum_tune_mask, spum_tune_texts, spum_tune_values);
static const struct snd_kcontrol_new spum_pre_tune0_controls[] = {
SOC_DAPM_ENUM("SPUM PRETUNE0 SEL", spum_pre_tune0_enum),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_pre_tune1_enum,
ABOX_SPUM_CTRL_TUNE_SEL, ABOX_PRE_TUNE_SEL_L(1),
spum_tune_mask, spum_tune_texts, spum_tune_values);
static const struct snd_kcontrol_new spum_pre_tune1_controls[] = {
SOC_DAPM_ENUM("SPUM PRETUNE1 SEL", spum_pre_tune1_enum),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_post_tune0_enum,
ABOX_SPUM_CTRL_TUNE_SEL, ABOX_POST_TUNE_SEL_L(0),
spum_tune_mask, spum_tune_texts, spum_tune_values);
static const struct snd_kcontrol_new spum_post_tune0_controls[] = {
SOC_DAPM_ENUM("SPUM POSTTUNE0 SEL", spum_post_tune0_enum),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_post_tune1_enum,
ABOX_SPUM_CTRL_TUNE_SEL, ABOX_POST_TUNE_SEL_L(1),
spum_tune_mask, spum_tune_texts, spum_tune_values);
static const struct snd_kcontrol_new spum_post_tune1_controls[] = {
SOC_DAPM_ENUM("SPUM POSTTUNE1 SEL", spum_post_tune1_enum),
};
static int atune_find_nsrc(struct snd_soc_component *cmpnt, int aid)
{
unsigned int val;
int ret;
val = snd_soc_component_read(cmpnt, ABOX_SPUM_CTRL_TUNE_SEL);
ret = (val & ABOX_PRE_TUNE_SEL_MASK(aid)) >> ABOX_PRE_TUNE_SEL_L(aid);
if (ret > 0x7)
ret = -EPIPE;
return ret;
}
static int atune_find_sifm(struct snd_soc_component *cmpnt, int aid)
{
unsigned int val;
int ret;
val = snd_soc_component_read(cmpnt, ABOX_SPUM_CTRL_TUNE_SEL);
ret = (val & ABOX_POST_TUNE_SEL_MASK(aid)) >> ABOX_POST_TUNE_SEL_L(aid);
if (ret > 0x7)
ret = -EPIPE;
return ret;
}
static int sifs_from_spus(struct abox_data *data, int sid)
{
return abox_cmpnt_spus_get_sifs(data, sid);
}
static int pretune_id_from_spus(struct abox_data *data, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int aid, ret = -EPIPE;
for (aid = 0; aid < COUNT_ATUNE; aid++) {
ret = atune_find_spus(cmpnt, aid);
if (ret == sid)
return aid;
}
return -EPIPE;
}
static int posttune_id_from_sifs(struct abox_data *data, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int aid, ret = -EPIPE;
for (aid = 0; aid < COUNT_ATUNE; aid++) {
ret = atune_find_sifs(cmpnt, aid);
if (ret == sid)
return aid;
}
return -EPIPE;
}
static int posttune_id_from_spus(struct abox_data *data, int sid)
{
int sifs = sifs_from_spus(data, sid);
if (sifs < 0)
return sifs;
else
return posttune_id_from_sifs(data, sifs);
}
static int pretune_id_from_nsrc(struct abox_data *data, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int aid, ret = -EPIPE;
for (aid = 0; aid < COUNT_ATUNE; aid++) {
ret = atune_find_nsrc(cmpnt, aid);
if (ret == sid)
return aid;
}
return -EPIPE;
}
static int posttune_id_from_sifm(struct abox_data *data, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int aid, ret = -EPIPE;
for (aid = 0; aid < COUNT_ATUNE; aid++) {
ret = atune_find_sifm(cmpnt, aid);
if (ret == sid)
return aid;
}
return -EPIPE;
}
static int posttune_id_from_nsrc(struct abox_data *data, int sid)
{
/* nsrc and sifm is matched by one to one */
return posttune_id_from_sifm(data, sid);
}
static int spus_pregain_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUS_USGAIN_CTRL(aid));
return !!(val & ATUNE_ENABLE_MASK);
}
static int spus_bqf_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUS_BQF_CTRL(aid));
return !!(val & (ATUNE_EQ_ENABLE_MASK | ATUNE_HPF_ENABLE_MASK));
}
static int spus_drc_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUS_DRC_CTRL(aid));
return !!(val & (ATUNE_DRC_ENABLE_MASK | ATUNE_LIMIT_ENABLE_MASK));
}
static int spus_postgain_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUS_DSGAIN_CTRL(aid));
return !!(val & ATUNE_ENABLE_MASK);
}
static int spum_pregain_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUM_USGAIN_CTRL(aid));
return !!(val & ATUNE_ENABLE_MASK);
}
static int spum_bqf_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUM_BQF_CTRL(aid));
return !!(val & (ATUNE_EQ_ENABLE_MASK | ATUNE_HPF_ENABLE_MASK));
}
static int spum_drc_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUM_DRC_CTRL(aid));
return !!(val & (ATUNE_DRC_ENABLE_MASK | ATUNE_LIMIT_ENABLE_MASK));
}
static int spum_postgain_enabled(struct abox_data *data, int aid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val;
val = snd_soc_component_read(cmpnt, ATUNE_SPUM_DSGAIN_CTRL(aid));
return !!(val & ATUNE_ENABLE_MASK);
}
static int spus_posttune_enabled(struct abox_data *data, int sid)
{
int aid = posttune_id_from_spus(data, sid);
if (aid < 0)
return 0;
return spus_bqf_enabled(data, aid) || spus_drc_enabled(data, aid)
|| spus_postgain_enabled(data, aid);
}
static int spum_pretune_enabled(struct abox_data *data, int sid)
{
int aid = pretune_id_from_nsrc(data, sid);
if (aid < 0)
return 0;
return spum_pregain_enabled(data, aid) || spum_bqf_enabled(data, aid);
}
static int spus_pregain_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
struct device *dev_dma;
unsigned int shift, mask, val, width, channels;
int ret = 0;
struct snd_pcm_hw_params params;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spus_pregain_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_SRC_USG_L(sid);
mask = ABOX_FUNC_CHAIN_SRC_USG_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUS_CTRL_FC_SRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
if (!spus_posttune_enabled(data, sid)) {
/* if pretune only is enabled,
* enable ASRC for bit conversion
*/
abox_cmpnt_asrc_enable(data, SNDRV_PCM_STREAM_PLAYBACK,
sid);
}
/* sync format */
dev_dma = data->dev_rdma[sid];
ret = abox_dma_hw_params_fixup(dev_dma, &params);
if (ret < 0) {
abox_err(data->dev, "%s: hw params get failed: %d\n",
__func__, ret);
goto out;
}
width = abox_dma_get_dst_bit_width(dev_dma);
channels = params_channels(&params);
val = abox_get_format(width, channels);
shift = ATUNE_FORMAT_L;
mask = ATUNE_FORMAT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUS_USGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): input format=%#x\n", __func__,
aid, sid, val);
}
out:
return ret;
}
static int spus_pregain0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
return spus_pregain_event(NULL, e, 0, 0);
}
static int spus_pregain1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
return spus_pregain_event(NULL, e, 1, 0);
}
static int spus_bqf_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val;
int ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spus_bqf_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_SRC_BQF_L(sid);
mask = ABOX_FUNC_CHAIN_SRC_BQF_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUS_CTRL_FC_SRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
/* atune can process 32bit only */
if (val)
abox_dma_set_dst_bit_width(data->dev_rdma[sid], 32);
}
out:
return ret;
}
static int spus_bqf0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spus_bqf1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spus_drc_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val;
int ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spus_drc_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_SRC_DRC_L(sid);
mask = ABOX_FUNC_CHAIN_SRC_DRC_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUS_CTRL_FC_SRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
/* atune can process 32bit only */
if (val)
abox_dma_set_dst_bit_width(data->dev_rdma[sid], 32);
}
out:
return ret;
}
static int spus_drc0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spus_drc1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spus_postgain_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val, rate, format;
int sifs_id, ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spus_postgain_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_SRC_DSG_L(sid);
mask = ABOX_FUNC_CHAIN_SRC_DSG_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUS_CTRL_FC_SRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
/* atune can process 32bit only */
if (val)
abox_dma_set_dst_bit_width(data->dev_rdma[sid], 32);
/* get sifs id */
sifs_id = sifs_from_spus(data, sid);
if (sifs_id < 0) {
abox_err(data->dev, "%s: invalid sifs: %d\n",
__func__, sifs_id);
goto out;
}
/* get rate */
rate = abox_cmpnt_sif_get_dst_rate(data,
SNDRV_PCM_STREAM_PLAYBACK, sifs_id);
/* sync rate */
val = ilog2((rate / 48000));
shift = ATUNE_SAMPLE_RATE_L;
mask = ATUNE_SAMPLE_RATE_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUS_DSGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): rate=%#x\n", __func__,
aid, sid, val);
/* get format */
format = abox_cmpnt_sif_get_dst_format(data,
SNDRV_PCM_STREAM_PLAYBACK, sifs_id);
/* sync input format */
val = format | (0x3 << 3); /* 32bit fixed */
shift = ATUNE_FORMAT_L;
mask = ATUNE_FORMAT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUS_DSGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): input format=%#x\n", __func__,
aid, sid, val);
/* sync output format */
val = format >> 0x3;
shift = ATUNE_DITHER_OUTPUT_BIT_L;
mask = ATUNE_DITHER_OUTPUT_BIT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUS_DSGAIN_BIT_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): output format=%#x\n", __func__,
aid, sid, val);
}
out:
return ret;
}
static int spus_postgain0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spus_postgain1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_pregain_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val;
int ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spum_pregain_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_NSRC_USG_L(sid);
mask = ABOX_FUNC_CHAIN_NSRC_USG_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUM_CTRL_FC_NSRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
/* atune can process 32bit only */
if (val)
abox_dma_set_dst_bit_width(data->dev_wdma[sid], 32);
/* sync format */
val = abox_cmpnt_sif_get_dst_format(data,
SNDRV_PCM_STREAM_CAPTURE, sid);
shift = ATUNE_FORMAT_L;
mask = ATUNE_FORMAT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUM_USGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): input format=%#x\n", __func__,
aid, sid, val);
}
out:
return ret;
}
static int spum_pregain0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_pregain1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_bqf_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val;
int ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spum_bqf_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_NSRC_BQF_L(sid);
mask = ABOX_FUNC_CHAIN_NSRC_BQF_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUM_CTRL_FC_NSRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
/* atune can process 32bit only */
if (val)
abox_dma_set_dst_bit_width(data->dev_wdma[sid], 32);
}
out:
return ret;
}
static int spum_bqf0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_bqf1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_drc_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int shift, mask, val;
int ret = 0;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spum_drc_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_NSRC_DRC_L(sid);
mask = ABOX_FUNC_CHAIN_NSRC_DRC_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUM_CTRL_FC_NSRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
if (!spum_pretune_enabled(data, sid)) {
/* if posttune only is enabled,
* enable ASRC for bit conversion
*/
abox_cmpnt_asrc_enable(data, SNDRV_PCM_STREAM_CAPTURE,
sid);
}
}
out:
return ret;
}
static int spum_drc0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_drc1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_postgain_event(struct abox_data *data, int e, int aid, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
struct device *dev_dma;
unsigned int shift, mask, val, width, channels, rate;
int ret = 0;
struct snd_pcm_hw_params params;
if (aid < 0 || sid < 0)
return 0;
abox_dbg(data->dev, "%s(%d, %d, %d)\n", __func__, e, aid, sid);
if (SND_SOC_DAPM_EVENT_ON(e)) {
/* sync function chain */
val = spum_postgain_enabled(data, aid);
shift = ABOX_FUNC_CHAIN_NSRC_DSG_L(sid);
mask = ABOX_FUNC_CHAIN_NSRC_DSG_MASK(sid);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SPUM_CTRL_FC_NSRC(sid),
mask, val << shift);
if (ret < 0) {
abox_err(data->dev, "%s: function chain set fail: %d\n",
__func__, ret);
goto out;
}
abox_dbg(data->dev, "%s(%d, %d, %d): %s\n", __func__,
e, aid, sid, val ? "connected" : "disconnected");
if (!spum_pretune_enabled(data, sid)) {
/* if posttune only is enabled,
* enable ASRC for bit conversion
*/
abox_cmpnt_asrc_enable(data, SNDRV_PCM_STREAM_CAPTURE,
sid);
}
/* get format */
dev_dma = data->dev_wdma[sid];
ret = abox_dma_hw_params_fixup(dev_dma, &params);
if (ret < 0) {
abox_err(dev_dma, "%s: hw params get failed: %d\n",
__func__, ret);
goto out;
}
rate = params_rate(&params);
channels = params_channels(&params);
width = abox_dma_get_dst_bit_width(dev_dma);
/* sync rate */
val = ilog2((rate / 48000));
shift = ATUNE_SAMPLE_RATE_L;
mask = ATUNE_SAMPLE_RATE_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUM_DSGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): rate=%#x\n", __func__,
aid, sid, val);
/* sync input format */
val = abox_get_format(32, channels); /* 32bit fixed */
shift = ATUNE_FORMAT_L;
mask = ATUNE_FORMAT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUM_DSGAIN_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): input format=%#x\n", __func__,
aid, sid, val);
/* sync output format */
val = (width / 8) - 1;
shift = ATUNE_DITHER_OUTPUT_BIT_L;
mask = ATUNE_DITHER_OUTPUT_BIT_MASK;
ret = snd_soc_component_update_bits(cmpnt,
ATUNE_SPUM_DSGAIN_BIT_CTRL(aid),
mask, val << shift);
abox_dbg(data->dev, "%s(%d, %d): output format=%#x\n", __func__,
aid, sid, val);
}
out:
return ret;
}
static int spum_postgain0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
static int spum_postgain1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
/* later use */
return 0;
}
/* later use */
#define ATUNE_EVENT_FLAGS 0
static const struct snd_soc_dapm_widget atune_widgets[] = {
SND_SOC_DAPM_MUX("SPUS PRETUNE0 IN", SND_SOC_NOPM, 0, 0,
spus_pre_tune0_controls),
SND_SOC_DAPM_DEMUX("SPUS PRETUNE0 OUT", SND_SOC_NOPM, 0, 0,
spus_pre_tune0_controls),
SND_SOC_DAPM_MUX("SPUS POSTTUNE0 IN", SND_SOC_NOPM, 0, 0,
spus_post_tune0_controls),
SND_SOC_DAPM_DEMUX("SPUS POSTTUNE0 OUT", SND_SOC_NOPM, 0, 0,
spus_post_tune0_controls),
SND_SOC_DAPM_PGA_E("SPUS PREGAIN0", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_pregain0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS BQF0", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_bqf0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS DRC0", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_drc0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS POSTGAIN0", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_postgain0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_MUX("SPUM PRETUNE0 IN", SND_SOC_NOPM, 0, 0,
spum_pre_tune0_controls),
SND_SOC_DAPM_DEMUX("SPUM PRETUNE0 OUT", SND_SOC_NOPM, 0, 0,
spum_pre_tune0_controls),
SND_SOC_DAPM_MUX("SPUM POSTTUNE0 IN", SND_SOC_NOPM, 0, 0,
spum_post_tune0_controls),
SND_SOC_DAPM_DEMUX("SPUM POSTTUNE0 OUT", SND_SOC_NOPM, 0, 0,
spum_post_tune0_controls),
SND_SOC_DAPM_PGA_E("SPUM PREGAIN0", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_pregain0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM BQF0", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_bqf0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM DRC0", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_drc0_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM POSTGAIN0", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_postgain0_event, ATUNE_EVENT_FLAGS),
};
static const struct snd_soc_dapm_widget atune1_widgets[] = {
SND_SOC_DAPM_MUX("SPUS PRETUNE1 IN", SND_SOC_NOPM, 0, 0,
spus_pre_tune1_controls),
SND_SOC_DAPM_DEMUX("SPUS PRETUNE1 OUT", SND_SOC_NOPM, 0, 0,
spus_pre_tune1_controls),
SND_SOC_DAPM_MUX("SPUS POSTTUNE1 IN", SND_SOC_NOPM, 0, 0,
spus_post_tune1_controls),
SND_SOC_DAPM_DEMUX("SPUS POSTTUNE1 OUT", SND_SOC_NOPM, 0, 0,
spus_post_tune1_controls),
SND_SOC_DAPM_PGA_E("SPUS PREGAIN1", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_pregain1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS BQF1", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_bqf1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS DRC1", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_drc1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUS POSTGAIN1", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_postgain1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_MUX("SPUM PRETUNE1 IN", SND_SOC_NOPM, 0, 0,
spum_pre_tune1_controls),
SND_SOC_DAPM_DEMUX("SPUM PRETUNE1 OUT", SND_SOC_NOPM, 0, 0,
spum_pre_tune1_controls),
SND_SOC_DAPM_MUX("SPUM POSTTUNE1 IN", SND_SOC_NOPM, 0, 0,
spum_post_tune1_controls),
SND_SOC_DAPM_DEMUX("SPUM POSTTUNE1 OUT", SND_SOC_NOPM, 0, 0,
spum_post_tune1_controls),
SND_SOC_DAPM_PGA_E("SPUM PREGAIN1", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_pregain1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM BQF1", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_bqf1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM DRC1", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_drc1_event, ATUNE_EVENT_FLAGS),
SND_SOC_DAPM_PGA_E("SPUM POSTGAIN1", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_postgain1_event, ATUNE_EVENT_FLAGS),
};
static const struct snd_soc_dapm_route atune_routes[] = {
/* sink, control, source */
{"SPUS PRETUNE0 IN", "SPUS0", "SPUS IN0"},
{"SPUS PRETUNE0 IN", "SPUS1", "SPUS IN1"},
{"SPUS PRETUNE0 IN", "SPUS2", "SPUS IN2"},
{"SPUS PRETUNE0 IN", "SPUS3", "SPUS IN3"},
{"SPUS PRETUNE0 IN", "SPUS4", "SPUS IN4"},
{"SPUS PRETUNE0 IN", "SPUS5", "SPUS IN5"},
{"SPUS PRETUNE0 IN", "SPUS6", "SPUS IN6"},
{"SPUS PRETUNE0 IN", "SPUS7", "SPUS IN7"},
{"SPUS PRETUNE0 IN", "SPUS8", "SPUS IN8"},
{"SPUS PRETUNE0 IN", "SPUS9", "SPUS IN9"},
{"SPUS PRETUNE0 IN", "SPUS10", "SPUS IN10"},
{"SPUS PRETUNE0 IN", "SPUS11", "SPUS IN11"},
{"SPUS PREGAIN0", NULL, "SPUS PRETUNE0 IN"},
{"SPUS PRETUNE0 OUT", NULL, "SPUS PREGAIN0"},
{"SPUS PGA0", "SPUS0", "SPUS PRETUNE0 OUT"},
{"SPUS PGA1", "SPUS1", "SPUS PRETUNE0 OUT"},
{"SPUS PGA2", "SPUS2", "SPUS PRETUNE0 OUT"},
{"SPUS PGA3", "SPUS3", "SPUS PRETUNE0 OUT"},
{"SPUS PGA4", "SPUS4", "SPUS PRETUNE0 OUT"},
{"SPUS PGA5", "SPUS5", "SPUS PRETUNE0 OUT"},
{"SPUS PGA6", "SPUS6", "SPUS PRETUNE0 OUT"},
{"SPUS PGA7", "SPUS7", "SPUS PRETUNE0 OUT"},
{"SPUS PGA8", "SPUS8", "SPUS PRETUNE0 OUT"},
{"SPUS PGA9", "SPUS9", "SPUS PRETUNE0 OUT"},
{"SPUS PGA10", "SPUS10", "SPUS PRETUNE0 OUT"},
{"SPUS PGA11", "SPUS11", "SPUS PRETUNE0 OUT"},
{"SPUS POSTTUNE0 IN", "SIFS0", "SIFS0"},
{"SPUS POSTTUNE0 IN", "SIFS1", "SIFS1"},
{"SPUS POSTTUNE0 IN", "SIFS2", "SIFS2"},
{"SPUS POSTTUNE0 IN", "SIFS3", "SIFS3"},
{"SPUS POSTTUNE0 IN", "SIFS4", "SIFS4"},
{"SPUS POSTTUNE0 IN", "SIFS5", "SIFS5"},
{"SPUS POSTTUNE0 IN", "SIFS6", "SIFS6"},
{"SPUS BQF0", NULL, "SPUS POSTTUNE0 IN"},
{"SPUS DRC0", NULL, "SPUS BQF0"},
{"SPUS POSTGAIN0", NULL, "SPUS DRC0"},
{"SPUS POSTTUNE0 OUT", NULL, "SPUS POSTGAIN0"},
{"SIFS0 PGA", "SIFS0", "SPUS POSTTUNE0 OUT"},
{"SIFS1 PGA", "SIFS1", "SPUS POSTTUNE0 OUT"},
{"SIFS2 PGA", "SIFS2", "SPUS POSTTUNE0 OUT"},
{"SIFS3 PGA", "SIFS3", "SPUS POSTTUNE0 OUT"},
{"SIFS4 PGA", "SIFS4", "SPUS POSTTUNE0 OUT"},
{"SIFS5 PGA", "SIFS5", "SPUS POSTTUNE0 OUT"},
{"SIFS6 PGA", "SIFS6", "SPUS POSTTUNE0 OUT"},
{"SPUM PRETUNE0 IN", "SIFM0", "NSRC0 In"},
{"SPUM PRETUNE0 IN", "SIFM1", "NSRC1 In"},
{"SPUM PRETUNE0 IN", "SIFM2", "NSRC2 In"},
{"SPUM PRETUNE0 IN", "SIFM3", "NSRC3 In"},
{"SPUM PRETUNE0 IN", "SIFM4", "NSRC4 In"},
{"SPUM PRETUNE0 IN", "SIFM5", "NSRC5 In"},
{"SPUM PRETUNE0 IN", "SIFM6", "NSRC6 In"},
{"SPUM PRETUNE0 IN", "SIFM7", "NSRC7 In"},
{"SPUM PRETUNE0 IN", "SIFM8", "NSRC8 In"},
{"SPUM PRETUNE0 IN", "SIFM9", "NSRC9 In"},
{"SPUM PRETUNE0 IN", "SIFM10", "NSRC10 In"},
{"SPUM PRETUNE0 IN", "SIFM11", "NSRC11 In"},
{"SPUM PREGAIN0", NULL, "SPUM PRETUNE0 IN"},
{"SPUM BQF0", NULL, "SPUM PREGAIN0"},
{"SPUM PRETUNE0 OUT", NULL, "SPUM BQF0"},
{"NSRC0 PGA", "SIFM0", "SPUM PRETUNE0 OUT"},
{"NSRC1 PGA", "SIFM1", "SPUM PRETUNE0 OUT"},
{"NSRC2 PGA", "SIFM2", "SPUM PRETUNE0 OUT"},
{"NSRC3 PGA", "SIFM3", "SPUM PRETUNE0 OUT"},
{"NSRC4 PGA", "SIFM4", "SPUM PRETUNE0 OUT"},
{"NSRC5 PGA", "SIFM5", "SPUM PRETUNE0 OUT"},
{"NSRC6 PGA", "SIFM6", "SPUM PRETUNE0 OUT"},
{"NSRC7 PGA", "SIFM7", "SPUM PRETUNE0 OUT"},
{"NSRC8 PGA", "SIFM8", "SPUM PRETUNE0 OUT"},
{"NSRC9 PGA", "SIFM9", "SPUM PRETUNE0 OUT"},
{"NSRC10 PGA", "SIFM10", "SPUM PRETUNE0 OUT"},
{"NSRC11 PGA", "SIFM11", "SPUM PRETUNE0 OUT"},
{"SPUM POSTTUNE0 IN", "SIFM0", "SPUM ASRC0"},
{"SPUM POSTTUNE0 IN", "SIFM1", "SPUM ASRC1"},
{"SPUM POSTTUNE0 IN", "SIFM2", "SPUM ASRC2"},
{"SPUM POSTTUNE0 IN", "SIFM3", "SPUM ASRC3"},
{"SPUM POSTTUNE0 IN", "SIFM4", "SPUM ASRC4"},
{"SPUM POSTTUNE0 IN", "SIFM5", "SPUM ASRC5"},
{"SPUM POSTTUNE0 IN", "SIFM6", "SPUM ASRC6"},
{"SPUM POSTTUNE0 IN", "SIFM7", "SPUM ASRC7"},
{"SPUM POSTTUNE0 IN", "SIFM8", "SPUM ASRC8"},
{"SPUM POSTTUNE0 IN", "SIFM9", "SPUM ASRC9"},
{"SPUM POSTTUNE0 IN", "SIFM10", "SPUM ASRC10"},
{"SPUM POSTTUNE0 IN", "SIFM11", "SPUM ASRC11"},
{"SPUM DRC0", NULL, "SPUM POSTTUNE0 IN"},
{"SPUM POSTGAIN0", NULL, "SPUM DRC0"},
{"SPUM POSTTUNE0 OUT", NULL, "SPUM POSTGAIN0"},
{"SPUM PGA0", "SIFM0", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA1", "SIFM1", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA2", "SIFM2", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA3", "SIFM3", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA4", "SIFM4", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA5", "SIFM5", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA6", "SIFM6", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA7", "SIFM7", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA8", "SIFM8", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA9", "SIFM9", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA10", "SIFM10", "SPUM POSTTUNE0 OUT"},
{"SPUM PGA11", "SIFM11", "SPUM POSTTUNE0 OUT"},
};
static const struct snd_soc_dapm_route atune1_routes[] = {
/* sink, control, source */
{"SPUS PRETUNE1 IN", "SPUS0", "SPUS IN0"},
{"SPUS PRETUNE1 IN", "SPUS1", "SPUS IN1"},
{"SPUS PRETUNE1 IN", "SPUS2", "SPUS IN2"},
{"SPUS PRETUNE1 IN", "SPUS3", "SPUS IN3"},
{"SPUS PRETUNE1 IN", "SPUS4", "SPUS IN4"},
{"SPUS PRETUNE1 IN", "SPUS5", "SPUS IN5"},
{"SPUS PRETUNE1 IN", "SPUS6", "SPUS IN6"},
{"SPUS PRETUNE1 IN", "SPUS7", "SPUS IN7"},
{"SPUS PRETUNE1 IN", "SPUS8", "SPUS IN8"},
{"SPUS PRETUNE1 IN", "SPUS9", "SPUS IN9"},
{"SPUS PRETUNE1 IN", "SPUS10", "SPUS IN10"},
{"SPUS PRETUNE1 IN", "SPUS11", "SPUS IN11"},
{"SPUS PREGAIN1", NULL, "SPUS PRETUNE1 IN"},
{"SPUS PRETUNE1 OUT", NULL, "SPUS PREGAIN1"},
{"SPUS PGA0", "SPUS0", "SPUS PRETUNE1 OUT"},
{"SPUS PGA1", "SPUS1", "SPUS PRETUNE1 OUT"},
{"SPUS PGA2", "SPUS2", "SPUS PRETUNE1 OUT"},
{"SPUS PGA3", "SPUS3", "SPUS PRETUNE1 OUT"},
{"SPUS PGA4", "SPUS4", "SPUS PRETUNE1 OUT"},
{"SPUS PGA5", "SPUS5", "SPUS PRETUNE1 OUT"},
{"SPUS PGA6", "SPUS6", "SPUS PRETUNE1 OUT"},
{"SPUS PGA7", "SPUS7", "SPUS PRETUNE1 OUT"},
{"SPUS PGA8", "SPUS8", "SPUS PRETUNE1 OUT"},
{"SPUS PGA9", "SPUS9", "SPUS PRETUNE1 OUT"},
{"SPUS PGA10", "SPUS10", "SPUS PRETUNE1 OUT"},
{"SPUS PGA11", "SPUS11", "SPUS PRETUNE1 OUT"},
{"SPUS POSTTUNE1 IN", "SIFS0", "SIFS0"},
{"SPUS POSTTUNE1 IN", "SIFS1", "SIFS1"},
{"SPUS POSTTUNE1 IN", "SIFS2", "SIFS2"},
{"SPUS POSTTUNE1 IN", "SIFS3", "SIFS3"},
{"SPUS POSTTUNE1 IN", "SIFS4", "SIFS4"},
{"SPUS POSTTUNE1 IN", "SIFS5", "SIFS5"},
{"SPUS POSTTUNE1 IN", "SIFS6", "SIFS6"},
{"SPUS BQF1", NULL, "SPUS POSTTUNE1 IN"},
{"SPUS DRC1", NULL, "SPUS BQF1"},
{"SPUS POSTGAIN1", NULL, "SPUS DRC1"},
{"SPUS POSTTUNE1 OUT", NULL, "SPUS POSTGAIN1"},
{"SIFS0 PGA", "SIFS0", "SPUS POSTTUNE1 OUT"},
{"SIFS1 PGA", "SIFS1", "SPUS POSTTUNE1 OUT"},
{"SIFS2 PGA", "SIFS2", "SPUS POSTTUNE1 OUT"},
{"SIFS3 PGA", "SIFS3", "SPUS POSTTUNE1 OUT"},
{"SIFS4 PGA", "SIFS4", "SPUS POSTTUNE1 OUT"},
{"SIFS5 PGA", "SIFS5", "SPUS POSTTUNE1 OUT"},
{"SIFS6 PGA", "SIFS6", "SPUS POSTTUNE1 OUT"},
{"SPUM PRETUNE1 IN", "SIFM0", "NSRC0 In"},
{"SPUM PRETUNE1 IN", "SIFM1", "NSRC1 In"},
{"SPUM PRETUNE1 IN", "SIFM2", "NSRC2 In"},
{"SPUM PRETUNE1 IN", "SIFM3", "NSRC3 In"},
{"SPUM PRETUNE1 IN", "SIFM4", "NSRC4 In"},
{"SPUM PRETUNE1 IN", "SIFM5", "NSRC5 In"},
{"SPUM PRETUNE1 IN", "SIFM6", "NSRC6 In"},
{"SPUM PRETUNE1 IN", "SIFM7", "NSRC7 In"},
{"SPUM PRETUNE1 IN", "SIFM8", "NSRC8 In"},
{"SPUM PRETUNE1 IN", "SIFM9", "NSRC9 In"},
{"SPUM PRETUNE1 IN", "SIFM10", "NSRC10 In"},
{"SPUM PRETUNE1 IN", "SIFM11", "NSRC11 In"},
{"SPUM PREGAIN1", NULL, "SPUM PRETUNE1 IN"},
{"SPUM BQF1", NULL, "SPUM PREGAIN1"},
{"SPUM PRETUNE1 OUT", NULL, "SPUM BQF1"},
{"NSRC0 PGA", "SIFM0", "SPUM PRETUNE1 OUT"},
{"NSRC1 PGA", "SIFM1", "SPUM PRETUNE1 OUT"},
{"NSRC2 PGA", "SIFM2", "SPUM PRETUNE1 OUT"},
{"NSRC3 PGA", "SIFM3", "SPUM PRETUNE1 OUT"},
{"NSRC4 PGA", "SIFM4", "SPUM PRETUNE1 OUT"},
{"NSRC5 PGA", "SIFM5", "SPUM PRETUNE1 OUT"},
{"NSRC6 PGA", "SIFM6", "SPUM PRETUNE1 OUT"},
{"NSRC7 PGA", "SIFM7", "SPUM PRETUNE1 OUT"},
{"NSRC8 PGA", "SIFM8", "SPUM PRETUNE1 OUT"},
{"NSRC9 PGA", "SIFM9", "SPUM PRETUNE1 OUT"},
{"NSRC10 PGA", "SIFM10", "SPUM PRETUNE1 OUT"},
{"NSRC11 PGA", "SIFM11", "SPUM PRETUNE1 OUT"},
{"SPUM POSTTUNE1 IN", "SIFM0", "SPUM ASRC0"},
{"SPUM POSTTUNE1 IN", "SIFM1", "SPUM ASRC1"},
{"SPUM POSTTUNE1 IN", "SIFM2", "SPUM ASRC2"},
{"SPUM POSTTUNE1 IN", "SIFM3", "SPUM ASRC3"},
{"SPUM POSTTUNE1 IN", "SIFM4", "SPUM ASRC4"},
{"SPUM POSTTUNE1 IN", "SIFM5", "SPUM ASRC5"},
{"SPUM POSTTUNE1 IN", "SIFM6", "SPUM ASRC6"},
{"SPUM POSTTUNE1 IN", "SIFM7", "SPUM ASRC7"},
{"SPUM POSTTUNE1 IN", "SIFM8", "SPUM ASRC8"},
{"SPUM POSTTUNE1 IN", "SIFM9", "SPUM ASRC9"},
{"SPUM POSTTUNE1 IN", "SIFM10", "SPUM ASRC10"},
{"SPUM POSTTUNE1 IN", "SIFM11", "SPUM ASRC11"},
{"SPUM DRC1", NULL, "SPUM POSTTUNE1 IN"},
{"SPUM POSTGAIN1", NULL, "SPUM DRC1"},
{"SPUM POSTTUNE1 OUT", NULL, "SPUM POSTGAIN1"},
{"SPUM PGA0", "SIFM0", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA1", "SIFM1", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA2", "SIFM2", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA3", "SIFM3", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA4", "SIFM4", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA5", "SIFM5", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA6", "SIFM6", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA7", "SIFM7", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA8", "SIFM8", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA9", "SIFM9", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA10", "SIFM10", "SPUM POSTTUNE1 OUT"},
{"SPUM PGA11", "SIFM11", "SPUM POSTTUNE1 OUT"},
};
int abox_atune_probe(struct abox_data *data, int count)
{
struct snd_soc_component *cmpnt = data->cmpnt;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
int ret;
if (!cmpnt)
return -EAGAIN;
if (count < 1)
goto out;
ret = snd_soc_add_component_controls(cmpnt, atune_controls,
ARRAY_SIZE(atune_controls));
if (ret < 0)
return ret;
ret = snd_soc_dapm_new_controls(dapm, atune_widgets,
ARRAY_SIZE(atune_widgets));
if (ret < 0)
return ret;
ret = snd_soc_dapm_add_routes(dapm, atune_routes,
ARRAY_SIZE(atune_routes));
if (ret < 0)
return ret;
if (count < 2)
goto out;
ret = snd_soc_add_component_controls(cmpnt, atune1_controls,
ARRAY_SIZE(atune1_controls));
if (ret < 0)
return ret;
ret = snd_soc_dapm_new_controls(dapm, atune1_widgets,
ARRAY_SIZE(atune1_widgets));
if (ret < 0)
return ret;
ret = snd_soc_dapm_add_routes(dapm, atune1_routes,
ARRAY_SIZE(atune1_routes));
if (ret < 0)
return ret;
out:
abox_info(cmpnt->dev, "atune probed\n");
return 0;
}
int abox_atune_remove(struct abox_data *data)
{
/* widgets and controls would be removed with component */
return 0;
}
bool abox_atune_spus_posttune_connected(struct abox_data *data, int id)
{
return spus_posttune_enabled(data, id);
}
bool abox_atune_spum_pretune_connected(struct abox_data *data, int id)
{
return spum_pretune_enabled(data, id);
}
int abox_atune_dapm_event(struct abox_data *data, int e, int stream, int sid)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int mask;
int aid, ret = 0;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* clear atune connection to function chain */
mask = ABOX_FUNC_CHAIN_SRC_USG_MASK(sid) |
ABOX_FUNC_CHAIN_SRC_BQF_MASK(sid) |
ABOX_FUNC_CHAIN_SRC_DRC_MASK(sid) |
ABOX_FUNC_CHAIN_SRC_DSG_MASK(sid);
snd_soc_component_update_bits(cmpnt,
ABOX_SPUS_CTRL_FC_SRC(sid), mask, 0x0);
aid = posttune_id_from_spus(data, sid);
if (aid >= 0) {
ret = spus_bqf_event(data, e, aid, sid);
if (ret < 0)
goto err;
ret = spus_drc_event(data, e, aid, sid);
if (ret < 0)
goto err;
ret = spus_postgain_event(data, e, aid, sid);
if (ret < 0)
goto err;
}
aid = pretune_id_from_spus(data, sid);
if (aid >= 0) {
ret = spus_pregain_event(data, e, aid, sid);
if (ret < 0)
goto err;
}
} else {
/* clear atune connection to function chain */
mask = ABOX_FUNC_CHAIN_NSRC_USG_MASK(sid) |
ABOX_FUNC_CHAIN_NSRC_BQF_MASK(sid) |
ABOX_FUNC_CHAIN_NSRC_DRC_MASK(sid) |
ABOX_FUNC_CHAIN_NSRC_DSG_MASK(sid);
snd_soc_component_update_bits(cmpnt,
ABOX_SPUM_CTRL_FC_NSRC(sid), mask, 0x0);
aid = pretune_id_from_nsrc(data, sid);
if (aid >= 0) {
ret = spum_pregain_event(data, e, aid, sid);
if (ret < 0)
goto err;
ret = spum_bqf_event(data, e, aid, sid);
if (ret < 0)
goto err;
}
aid = posttune_id_from_nsrc(data, sid);
if (aid >= 0) {
ret = spum_drc_event(data, e, aid, sid);
if (ret < 0)
goto err;
ret = spum_postgain_event(data, e, aid, sid);
if (ret < 0)
goto err;
}
}
err:
return ret;
}