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

6057 lines
177 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ALSA SoC - Samsung Abox Component driver
*
* Copyright (c) 2018 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 <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/sched/clock.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "abox.h"
#include "abox_dump.h"
#include "abox_vdma.h"
#include "abox_dma.h"
#include "abox_if.h"
#include "abox_cmpnt.h"
#include "abox_vss.h"
#include "abox_memlog.h"
enum asrc_tick {
TICK_CP = 0x0,
TICK_UAIF0 = 0x1,
TICK_UAIF1 = 0x2,
TICK_UAIF2 = 0x3,
TICK_UAIF3 = 0x4,
TICK_UAIF4 = 0x5,
TICK_UAIF5 = 0x6,
TICK_UAIF6 = 0x7,
TICK_USB = 0x8,
TICK_BCLK_CP = 0x9,
TICK_BCLK_SPDY = 0xA,
TICK_SYNC,
};
enum asrc_ratio {
RATIO_1,
RATIO_2,
RATIO_4,
RATIO_8,
RATIO_16,
RATIO_32,
RATIO_64,
RATIO_128,
RATIO_256,
};
enum asrc_rate {
RATE_8000,
RATE_16000,
RATE_32000,
RATE_40000,
RATE_44100,
RATE_48000,
RATE_96000,
RATE_192000,
RATE_384000,
ASRC_RATE_COUNT,
};
static const unsigned int asrc_rates[] = {
8000, 16000, 32000, 40000, 44100, 48000, 96000, 192000, 384000
};
static enum asrc_rate to_asrc_rate(unsigned int rate)
{
enum asrc_rate arate;
for (arate = RATE_8000; arate < ASRC_RATE_COUNT; arate++) {
if (asrc_rates[arate] == rate)
break;
}
return (arate < ASRC_RATE_COUNT) ? arate : RATE_48000;
}
struct asrc_ctrl {
unsigned int isr;
unsigned int osr;
enum asrc_ratio ovsf;
unsigned int ifactor;
enum asrc_ratio dcmf;
};
static const struct asrc_ctrl asrc_table[ASRC_RATE_COUNT][ASRC_RATE_COUNT] = {
/* isr, osr, ovsf, ifactor, dcmf */
{
{ 8000, 8000, RATIO_8, 65536, RATIO_8},
{ 8000, 16000, RATIO_8, 65536, RATIO_8},
{ 8000, 32000, RATIO_8, 98304, RATIO_8},
{ 8000, 40000, RATIO_8, 76800, RATIO_8},
{ 8000, 44100, RATIO_8, 88200, RATIO_8},
{ 8000, 48000, RATIO_8, 98304, RATIO_8},
{ 8000, 96000, RATIO_8, 98304, RATIO_4},
{ 8000, 192000, RATIO_8, 98304, RATIO_2},
{ 8000, 384000, RATIO_8, 98304, RATIO_1},
},
{
{ 16000, 8000, RATIO_8, 32768, RATIO_8},
{ 16000, 16000, RATIO_8, 65536, RATIO_8},
{ 16000, 32000, RATIO_8, 65536, RATIO_8},
{ 16000, 40000, RATIO_8, 76800, RATIO_8},
{ 16000, 44100, RATIO_8, 88200, RATIO_8},
{ 16000, 48000, RATIO_8, 98304, RATIO_8},
{ 16000, 96000, RATIO_8, 98304, RATIO_8},
{ 16000, 192000, RATIO_8, 98304, RATIO_4},
{ 16000, 384000, RATIO_8, 98304, RATIO_2},
},
{
{ 32000, 8000, RATIO_8, 24576, RATIO_8},
{ 32000, 16000, RATIO_8, 32768, RATIO_8},
{ 32000, 32000, RATIO_8, 65536, RATIO_8},
{ 32000, 40000, RATIO_8, 76800, RATIO_8},
{ 32000, 44100, RATIO_8, 88200, RATIO_8},
{ 32000, 48000, RATIO_8, 98304, RATIO_8},
{ 32000, 96000, RATIO_8, 73728, RATIO_2},
{ 32000, 192000, RATIO_8, 98304, RATIO_2},
{ 32000, 384000, RATIO_8, 98304, RATIO_1},
},
{
{ 40000, 8000, RATIO_8, 15360, RATIO_8},
{ 40000, 16000, RATIO_8, 30720, RATIO_8},
{ 40000, 32000, RATIO_8, 61440, RATIO_8},
{ 40000, 40000, RATIO_8, 65536, RATIO_8},
{ 40000, 44100, RATIO_8, 88200, RATIO_8},
{ 40000, 48000, RATIO_8, 61440, RATIO_8},
{ 40000, 96000, RATIO_8, 61440, RATIO_4},
{ 40000, 192000, RATIO_8, 61440, RATIO_2},
{ 40000, 384000, RATIO_8, 61440, RATIO_1},
},
{
{ 44100, 8000, RATIO_8, 20480, RATIO_8},
{ 44100, 16000, RATIO_8, 40960, RATIO_8},
{ 44100, 32000, RATIO_8, 61440, RATIO_8},
{ 44100, 40000, RATIO_8, 80000, RATIO_8},
{ 44100, 44100, RATIO_8, 61440, RATIO_8},
{ 44100, 48000, RATIO_8, 61440, RATIO_8},
{ 44100, 96000, RATIO_8, 61440, RATIO_2},
{ 44100, 192000, RATIO_8, 61440, RATIO_2},
{ 44100, 384000, RATIO_8, 61440, RATIO_1},
},
{
{ 48000, 8000, RATIO_8, 16384, RATIO_8},
{ 48000, 16000, RATIO_8, 32768, RATIO_8},
{ 48000, 32000, RATIO_8, 65536, RATIO_8},
{ 48000, 40000, RATIO_8, 51200, RATIO_8},
{ 48000, 44100, RATIO_8, 88200, RATIO_8},
{ 48000, 48000, RATIO_8, 65536, RATIO_8},
{ 48000, 96000, RATIO_8, 32768, RATIO_2},
{ 48000, 192000, RATIO_8, 65536, RATIO_2},
{ 48000, 384000, RATIO_8, 65536, RATIO_1},
},
{
{ 96000, 8000, RATIO_2, 32768, RATIO_8},
{ 96000, 16000, RATIO_2, 65536, RATIO_8},
{ 96000, 32000, RATIO_2, 98304, RATIO_8},
{ 96000, 40000, RATIO_4, 51200, RATIO_8},
{ 96000, 44100, RATIO_4, 88200, RATIO_8},
{ 96000, 48000, RATIO_4, 65536, RATIO_8},
{ 96000, 96000, RATIO_4, 98304, RATIO_8},
{ 96000, 192000, RATIO_4, 98304, RATIO_4},
{ 96000, 384000, RATIO_4, 98304, RATIO_2},
},
{
{192000, 8000, RATIO_2, 16384, RATIO_8},
{192000, 16000, RATIO_2, 32768, RATIO_8},
{192000, 32000, RATIO_2, 32768, RATIO_8},
{192000, 40000, RATIO_2, 51200, RATIO_8},
{192000, 44100, RATIO_4, 44100, RATIO_8},
{192000, 48000, RATIO_2, 98304, RATIO_8},
{192000, 96000, RATIO_1, 98304, RATIO_2},
{192000, 192000, RATIO_1, 98304, RATIO_1},
{192000, 384000, RATIO_2, 98304, RATIO_1},
},
{
{384000, 8000, RATIO_1, 16384, RATIO_8},
{384000, 16000, RATIO_1, 32768, RATIO_8},
{384000, 32000, RATIO_1, 32768, RATIO_8},
{384000, 40000, RATIO_1, 51200, RATIO_8},
{384000, 44100, RATIO_1, 56448, RATIO_8},
{384000, 48000, RATIO_1, 32768, RATIO_4},
{384000, 96000, RATIO_1, 65536, RATIO_4},
{384000, 192000, RATIO_1, 98304, RATIO_2},
{384000, 384000, RATIO_1, 98304, RATIO_1},
},
};
static unsigned int cal_ofactor(const struct asrc_ctrl *ctrl)
{
unsigned int isr, osr, ofactor;
isr = (ctrl->isr / 100) << ctrl->ovsf;
osr = (ctrl->osr / 100) << ctrl->dcmf;
ofactor = ctrl->ifactor * isr / osr;
return ofactor;
}
static unsigned int is_limit(unsigned int is_default)
{
return is_default / (100 / 5); /* 5% */
}
static unsigned int os_limit(unsigned int os_default)
{
return os_default / (100 / 5); /* 5% */
}
static int sif_idx(enum ABOX_CONFIGMSG configmsg)
{
return configmsg - ((configmsg < SET_SIFS0_FORMAT) ?
SET_SIFS0_RATE : SET_SIFS0_FORMAT);
}
static unsigned int get_sif_rate(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg)
{
return data->sif_rate[sif_idx(configmsg)];
}
static void set_sif_rate(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg, unsigned int val)
{
data->sif_rate[sif_idx(configmsg)] = val;
}
static snd_pcm_format_t get_sif_format(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg)
{
return data->sif_format[sif_idx(configmsg)];
}
static void set_sif_format(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg, snd_pcm_format_t val)
{
data->sif_format[sif_idx(configmsg)] = val;
}
static int __maybe_unused get_sif_physical_width(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg)
{
snd_pcm_format_t format = get_sif_format(data, configmsg);
return snd_pcm_format_physical_width(format);
}
static int get_sif_width(struct abox_data *data, enum ABOX_CONFIGMSG configmsg)
{
return snd_pcm_format_width(get_sif_format(data, configmsg));
}
static void __maybe_unused set_sif_width(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg, int width)
{
struct device *dev = data->dev;
snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16;
switch (width) {
case 16:
format = SNDRV_PCM_FORMAT_S16;
break;
case 24:
format = SNDRV_PCM_FORMAT_S24;
break;
case 32:
format = SNDRV_PCM_FORMAT_S32;
break;
default:
abox_err(dev, "%s(%d): invalid argument\n", __func__, width);
}
set_sif_format(data, configmsg, format);
}
static unsigned int get_sif_channels(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg)
{
return data->sif_channels[sif_idx(configmsg)];
}
static void set_sif_channels(struct abox_data *data,
enum ABOX_CONFIGMSG configmsg, unsigned int val)
{
data->sif_channels[sif_idx(configmsg)] = val;
}
static int rate_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 abox_data *data = dev_get_drvdata(dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = get_sif_rate(data, reg);
abox_dbg(dev, "%s(%#x): %u\n", __func__, reg, val);
ucontrol->value.integer.value[0] = val;
return 0;
}
static int rate_put_ipc(struct device *adev, unsigned int val,
enum ABOX_CONFIGMSG configmsg)
{
static DEFINE_MUTEX(lock);
struct abox_data *data = dev_get_drvdata(adev);
ABOX_IPC_MSG msg;
struct IPC_ABOX_CONFIG_MSG *abox_config_msg = &msg.msg.config;
int ret;
abox_dbg(adev, "%s(%u, %#x)\n", __func__, val, configmsg);
mutex_lock(&lock);
if (val > 0)
set_sif_rate(data, configmsg, val);
msg.ipcid = IPC_ABOX_CONFIG;
abox_config_msg->param1 = get_sif_rate(data, configmsg);
abox_config_msg->msgtype = configmsg;
ret = abox_request_ipc(adev, msg.ipcid, &msg, sizeof(msg), 0, 0);
if (ret < 0)
abox_err(adev, "%s(%u, %#x) failed: %d\n", __func__, val,
configmsg, ret);
mutex_unlock(&lock);
return ret;
}
static int rate_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 soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_info(dev, "%s(%#x, %u)\n", __func__, reg, val);
return rate_put_ipc(dev, val, reg);
}
static int format_put_ipc(struct device *adev, snd_pcm_format_t format,
unsigned int channels, enum ABOX_CONFIGMSG configmsg)
{
static DEFINE_MUTEX(lock);
struct abox_data *data = dev_get_drvdata(adev);
ABOX_IPC_MSG msg;
struct IPC_ABOX_CONFIG_MSG *abox_config_msg = &msg.msg.config;
int width = snd_pcm_format_width(format);
int ret;
abox_dbg(adev, "%s(%d, %u, %#x)\n", __func__, width, channels,
configmsg);
mutex_lock(&lock);
if (format > 0)
set_sif_format(data, configmsg, format);
if (channels > 0)
set_sif_channels(data, configmsg, channels);
width = get_sif_width(data, configmsg);
channels = get_sif_channels(data, configmsg);
/* update manually for regmap cache sync */
switch (configmsg) {
case SET_SIFS0_RATE:
case SET_SIFS0_FORMAT:
regmap_update_bits(data->regmap, ABOX_SPUS_CTRL1,
ABOX_MIXP_FORMAT_MASK,
abox_get_format(width, channels) <<
ABOX_MIXP_FORMAT_L);
break;
default:
/* Nothing to do */
break;
}
msg.ipcid = IPC_ABOX_CONFIG;
abox_config_msg->param1 = width;
abox_config_msg->param2 = channels;
abox_config_msg->msgtype = configmsg;
ret = abox_request_ipc(adev, msg.ipcid, &msg, sizeof(msg), 0, 0);
if (ret < 0)
abox_err(adev, "%d(%d bit, %u channels) failed: %d\n", configmsg,
width, channels, ret);
mutex_unlock(&lock);
return ret;
}
static int width_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 abox_data *data = dev_get_drvdata(dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = get_sif_width(data, reg);
abox_dbg(dev, "%s(%#x): %u\n", __func__, reg, val);
ucontrol->value.integer.value[0] = val;
return 0;
}
static int width_put_ipc(struct device *dev, unsigned int val,
enum ABOX_CONFIGMSG configmsg)
{
snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16;
abox_dbg(dev, "%s(%u, %#x)\n", __func__, val, configmsg);
switch (val) {
case 16:
format = SNDRV_PCM_FORMAT_S16;
break;
case 24:
format = SNDRV_PCM_FORMAT_S24;
break;
case 32:
format = SNDRV_PCM_FORMAT_S32;
break;
default:
abox_warn(dev, "%s(%u, %#x) invalid argument\n", __func__,
val, configmsg);
break;
}
return format_put_ipc(dev, format, 0, configmsg);
}
static int width_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 soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_info(dev, "%s(%#x, %u)\n", __func__, reg, val);
return width_put_ipc(dev, val, reg);
}
static int channels_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 abox_data *data = dev_get_drvdata(dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = get_sif_channels(data, reg);
abox_dbg(dev, "%s(%#x): %u\n", __func__, reg, val);
ucontrol->value.integer.value[0] = val;
return 0;
}
static int channels_put_ipc(struct device *dev, unsigned int val,
enum ABOX_CONFIGMSG configmsg)
{
unsigned int channels = val;
abox_dbg(dev, "%s(%u, %#x)\n", __func__, val, configmsg);
return format_put_ipc(dev, 0, channels, configmsg);
}
static int channels_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 soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_info(dev, "%s(%#x, %u)\n", __func__, reg, val);
return channels_put_ipc(dev, val, reg);
}
static int audio_mode_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 abox_data *data = dev_get_drvdata(dev);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int item;
abox_dbg(dev, "%s: %u\n", __func__, data->audio_mode);
item = snd_soc_enum_val_to_item(e, data->audio_mode);
ucontrol->value.enumerated.item[0] = item;
return 0;
}
static int audio_mode_put_ipc(struct device *dev, enum audio_mode mode)
{
struct abox_data *data = dev_get_drvdata(dev);
ABOX_IPC_MSG msg;
struct IPC_SYSTEM_MSG *system_msg = &msg.msg.system;
abox_dbg(dev, "%s(%d)\n", __func__, mode);
data->audio_mode_time = local_clock();
msg.ipcid = IPC_SYSTEM;
system_msg->msgtype = ABOX_SET_MODE;
system_msg->param1 = data->audio_mode = mode;
return abox_request_ipc(dev, msg.ipcid, &msg, sizeof(msg), 0, 0);
}
static int audio_mode_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int *item = ucontrol->value.enumerated.item;
struct abox_data *data = dev_get_drvdata(dev);
enum audio_mode mode;
if (item[0] >= e->items)
return -EINVAL;
mode = snd_soc_enum_item_to_val(e, item[0]);
abox_info(dev, "%s(%u)\n", __func__, mode);
if (IS_ENABLED(CONFIG_SOC_EXYNOS9830)) {
if (mode == MODE_IN_CALL)
abox_vss_notify_call(dev, data, 1);
else if (mode == MODE_NORMAL)
abox_vss_notify_call(dev, data, 0);
}
return audio_mode_put_ipc(dev, mode);
}
static const char * const audio_mode_enum_texts[] = {
"NORMAL",
"RINGTONE",
"IN_CALL",
"IN_COMMUNICATION",
"IN_VIDEOCALL",
"RESERVED0",
"RESERVED1",
"IN_LOOPBACK",
};
static const unsigned int audio_mode_enum_values[] = {
MODE_NORMAL,
MODE_RINGTONE,
MODE_IN_CALL,
MODE_IN_COMMUNICATION,
MODE_IN_VIDEOCALL,
MODE_RESERVED0,
MODE_RESERVED1,
MODE_IN_LOOPBACK,
};
SOC_VALUE_ENUM_SINGLE_DECL(audio_mode_enum, SND_SOC_NOPM, 0, 0,
audio_mode_enum_texts, audio_mode_enum_values);
static int sound_type_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 abox_data *data = dev_get_drvdata(dev);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int item;
abox_dbg(dev, "%s: %u\n", __func__, data->sound_type);
item = snd_soc_enum_val_to_item(e, data->sound_type);
ucontrol->value.enumerated.item[0] = item;
return 0;
}
static int sound_type_put_ipc(struct device *dev, enum sound_type type)
{
struct abox_data *data = dev_get_drvdata(dev);
ABOX_IPC_MSG msg;
struct IPC_SYSTEM_MSG *system_msg = &msg.msg.system;
abox_dbg(dev, "%s(%d)\n", __func__, type);
msg.ipcid = IPC_SYSTEM;
system_msg->msgtype = ABOX_SET_TYPE;
system_msg->param1 = data->sound_type = type;
return abox_request_ipc(dev, msg.ipcid, &msg, sizeof(msg), 0, 0);
}
static int sound_type_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int *item = ucontrol->value.enumerated.item;
enum sound_type type;
if (item[0] >= e->items)
return -EINVAL;
type = snd_soc_enum_item_to_val(e, item[0]);
abox_info(dev, "%s(%d)\n", __func__, type);
return sound_type_put_ipc(dev, type);
}
static const char * const sound_type_enum_texts[] = {
"VOICE",
"SPEAKER",
"HEADSET",
"BTVOICE",
"USB",
"CALLFWD",
};
static const unsigned int sound_type_enum_values[] = {
SOUND_TYPE_VOICE,
SOUND_TYPE_SPEAKER,
SOUND_TYPE_HEADSET,
SOUND_TYPE_BTVOICE,
SOUND_TYPE_USB,
SOUND_TYPE_CALLFWD,
};
SOC_VALUE_ENUM_SINGLE_DECL(sound_type_enum, SND_SOC_NOPM, 0, 0,
sound_type_enum_texts, sound_type_enum_values);
static int tickle_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 abox_data *data = dev_get_drvdata(dev);
abox_dbg(dev, "%s\n", __func__);
ucontrol->value.integer.value[0] = data->enabled;
return 0;
}
static int tickle_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;
long val = ucontrol->value.integer.value[0];
abox_dbg(dev, "%s(%ld)\n", __func__, val);
if (!!val)
pm_request_resume(dev);
return 0;
}
static unsigned int s_default = 36864;
static int asrc_factor_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 soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = s_default;
abox_dbg(dev, "%s(%#x): %u\n", __func__, reg, val);
ucontrol->value.integer.value[0] = val;
return 0;
}
static int asrc_factor_put_ipc(struct device *adev, unsigned int val,
enum ABOX_CONFIGMSG configmsg)
{
ABOX_IPC_MSG msg;
struct IPC_ABOX_CONFIG_MSG *abox_config_msg = &msg.msg.config;
int ret;
abox_dbg(adev, "%s(%u, %#x)\n", __func__, val, configmsg);
s_default = val;
msg.ipcid = IPC_ABOX_CONFIG;
abox_config_msg->param1 = s_default;
abox_config_msg->msgtype = configmsg;
ret = abox_request_ipc(adev, msg.ipcid, &msg, sizeof(msg), 0, 0);
if (ret < 0)
abox_err(adev, "%s(%u, %#x) failed: %d\n", __func__, val,
configmsg, ret);
return ret;
}
static int asrc_factor_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 soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_info(dev, "%s(%#x, %u)\n", __func__, reg, val);
return asrc_factor_put_ipc(dev, val, reg);
}
static bool spus_asrc_force_enable[] = {
false, false, false, false,
false, false, false, false,
false, false, false, false
};
static bool spum_asrc_force_enable[] = {
false, false, false, false,
false, false, false, false,
};
static int spus_asrc_enable_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;
long val = ucontrol->value.integer.value[0];
int idx, ret;
ret = sscanf(kcontrol->id.name, "%*s %*s ASRC%d", &idx);
if (ret < 1) {
abox_err(dev, "%s(%s): %d\n", __func__, kcontrol->id.name, ret);
return ret;
}
if (idx < 0 || idx >= ARRAY_SIZE(spus_asrc_force_enable)) {
abox_err(dev, "%s(%s): %d\n", __func__, kcontrol->id.name, idx);
return -EINVAL;
}
abox_info(dev, "%s(%ld, %d)\n", __func__, val, idx);
spus_asrc_force_enable[idx] = val;
return snd_soc_put_volsw(kcontrol, ucontrol);
}
static int spum_asrc_enable_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;
long val = ucontrol->value.integer.value[0];
int idx, ret;
ret = sscanf(kcontrol->id.name, "%*s %*s ASRC%d", &idx);
if (ret < 1) {
abox_err(dev, "%s(%s): %d\n", __func__, kcontrol->id.name, ret);
return ret;
}
if (idx < 0 || idx >= ARRAY_SIZE(spum_asrc_force_enable)) {
abox_err(dev, "%s(%s): %d\n", __func__, kcontrol->id.name, idx);
return -EINVAL;
}
abox_info(dev, "%s(%ld, %d)\n", __func__, val, idx);
spum_asrc_force_enable[idx] = val;
return snd_soc_put_volsw(kcontrol, ucontrol);
}
static int get_apf_coef(struct abox_data *data, int stream, int idx)
{
return data->apf_coef[stream ? 1 : 0][idx];
}
static void set_apf_coef(struct abox_data *data, int stream, int idx, int coef)
{
data->apf_coef[stream ? 1 : 0][idx] = coef;
}
static int asrc_apf_coef_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 abox_data *data = dev_get_drvdata(dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int stream = mc->reg;
int idx = mc->shift;
abox_dbg(dev, "%s(%d, %d)\n", __func__, stream, idx);
ucontrol->value.integer.value[0] = get_apf_coef(data, stream, idx);
return 0;
}
static int asrc_apf_coef_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 abox_data *data = dev_get_drvdata(dev);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int stream = mc->reg;
int idx = mc->shift;
long val = ucontrol->value.integer.value[0];
abox_dbg(dev, "%s(%d, %d, %ld)\n", __func__, stream, idx, val);
set_apf_coef(data, stream, idx, val);
return 0;
}
static int wake_lock_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 abox_data *data = dev_get_drvdata(dev);
unsigned int val = data->ws.active;
abox_dbg(dev, "%s: %u\n", __func__, val);
ucontrol->value.integer.value[0] = val;
return 0;
}
static int wake_lock_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 abox_data *data = dev_get_drvdata(dev);
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_info(dev, "%s(%u)\n", __func__, val);
if (val)
__pm_stay_awake(&data->ws);
else
__pm_relax(&data->ws);
return 0;
}
static int reset_log_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 abox_data *data = dev_get_drvdata(dev);
unsigned long *addr;
abox_dbg(dev, "%s: %u\n", __func__);
for (addr = data->slog_base + ABOX_SLOG_OFFSET; (void *)addr <
data->slog_base + data->slog_size; addr++) {
if (*addr) {
/* There is non-zero */
ucontrol->value.integer.value[0] = 0;
return 0;
}
}
/* Area is all zero */
ucontrol->value.integer.value[0] = 1;
return 0;
}
static int reset_log_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 abox_data *data = dev_get_drvdata(dev);
unsigned int val = (unsigned int)ucontrol->value.integer.value[0];
abox_dbg(dev, "%s(%u)\n", __func__, val);
if (val) {
abox_info(dev, "reset silent log area\n");
memset(data->slog_base + ABOX_SLOG_OFFSET, 0,
data->slog_size - ABOX_SLOG_OFFSET);
}
return 0;
}
static enum asrc_tick spus_asrc_os[] = {
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
};
static enum asrc_tick spus_asrc_is[] = {
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC
};
static enum asrc_tick spum_asrc_os[] = {
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
};
static enum asrc_tick spum_asrc_is[] = {
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
TICK_SYNC, TICK_SYNC, TICK_SYNC, TICK_SYNC,
};
static int spus_asrc_os_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick = spus_asrc_os[idx];
abox_dbg(dev, "%s(%d): %d\n", __func__, idx, tick);
item[0] = snd_soc_enum_val_to_item(e, tick);
return 0;
}
static int spus_asrc_os_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick;
if (item[0] >= e->items)
return -EINVAL;
tick = snd_soc_enum_item_to_val(e, item[0]);
abox_dbg(dev, "%s(%d, %d)\n", __func__, idx, tick);
spus_asrc_os[idx] = tick;
return 0;
}
static int spus_asrc_is_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick = spus_asrc_is[idx];
abox_dbg(dev, "%s(%d): %d\n", __func__, idx, tick);
item[0] = snd_soc_enum_val_to_item(e, tick);
return 0;
}
static int spus_asrc_is_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick;
if (item[0] >= e->items)
return -EINVAL;
tick = snd_soc_enum_item_to_val(e, item[0]);
abox_dbg(dev, "%s(%d, %d)\n", __func__, idx, tick);
spus_asrc_is[idx] = tick;
return 0;
}
static int spum_asrc_os_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick = spum_asrc_os[idx];
abox_dbg(dev, "%s(%d): %d\n", __func__, idx, tick);
item[0] = snd_soc_enum_val_to_item(e, tick);
return 0;
}
static int spum_asrc_os_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick;
if (item[0] >= e->items)
return -EINVAL;
tick = snd_soc_enum_item_to_val(e, item[0]);
abox_dbg(dev, "%s(%d, %d)\n", __func__, idx, tick);
spum_asrc_os[idx] = tick;
return 0;
}
static int spum_asrc_is_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick = spum_asrc_is[idx];
abox_dbg(dev, "%s(%d): %d\n", __func__, idx, tick);
item[0] = snd_soc_enum_val_to_item(e, tick);
return 0;
}
static int spum_asrc_is_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 soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int idx = e->reg;
unsigned int *item = ucontrol->value.enumerated.item;
enum asrc_tick tick;
if (item[0] >= e->items)
return -EINVAL;
tick = snd_soc_enum_item_to_val(e, item[0]);
abox_dbg(dev, "%s(%d, %d)\n", __func__, idx, tick);
spum_asrc_is[idx] = tick;
return 0;
}
static const struct snd_kcontrol_new cmpnt_controls[] = {
SOC_SINGLE_EXT("SIFS0 Rate", SET_SIFS0_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS1 Rate", SET_SIFS1_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS2 Rate", SET_SIFS2_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS3 Rate", SET_SIFS3_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS4 Rate", SET_SIFS4_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS5 Rate", SET_SIFS5_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFM0 Rate", SET_SIFM0_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFM1 Rate", SET_SIFM1_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFM2 Rate", SET_SIFM2_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFM3 Rate", SET_SIFM3_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFM4 Rate", SET_SIFM4_RATE, 8000, 384000, 0,
rate_get, rate_put),
SOC_SINGLE_EXT("SIFS0 Width", SET_SIFS0_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS1 Width", SET_SIFS1_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS2 Width", SET_SIFS2_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS3 Width", SET_SIFS3_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS4 Width", SET_SIFS4_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS5 Width", SET_SIFS5_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFM0 Width", SET_SIFM0_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFM1 Width", SET_SIFM1_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFM2 Width", SET_SIFM2_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFM3 Width", SET_SIFM3_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFM4 Width", SET_SIFM4_FORMAT, 16, 32, 0,
width_get, width_put),
SOC_SINGLE_EXT("SIFS0 Channel", SET_SIFS0_FORMAT, 1, 8, 0,
channels_get, channels_put),
SOC_VALUE_ENUM_EXT("Audio Mode", audio_mode_enum,
audio_mode_get, audio_mode_put),
SOC_VALUE_ENUM_EXT("Sound Type", sound_type_enum,
sound_type_get, sound_type_put),
SOC_SINGLE_EXT("Tickle", 0, 0, 1, 0, tickle_get, tickle_put),
SOC_SINGLE_EXT("Wakelock", 0, 0, 1, 0, wake_lock_get, wake_lock_put),
SOC_SINGLE_EXT("Reset Log", 0, 0, 1, 0, reset_log_get, reset_log_put),
SOC_SINGLE("NSRC0 Bridge", ABOX_ROUTE_CTRL2,
ABOX_NSRC_CONNECTION_TYPE_L(0), 1, 0),
SOC_SINGLE("NSRC1 Bridge", ABOX_ROUTE_CTRL2,
ABOX_NSRC_CONNECTION_TYPE_L(1), 1, 0),
SOC_SINGLE("NSRC2 Bridge", ABOX_ROUTE_CTRL2,
ABOX_NSRC_CONNECTION_TYPE_L(2), 1, 0),
SOC_SINGLE("NSRC3 Bridge", ABOX_ROUTE_CTRL2,
ABOX_NSRC_CONNECTION_TYPE_L(3), 1, 0),
SOC_SINGLE("NSRC4 Bridge", ABOX_ROUTE_CTRL2,
ABOX_NSRC_CONNECTION_TYPE_L(4), 1, 0),
SOC_SINGLE_EXT("ASRC Factor CP", SET_ASRC_FACTOR_CP, 0, 0x1ffff, 0,
asrc_factor_get, asrc_factor_put),
SOC_SINGLE("MIXP Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_MIXP_DUMMY_START_L, 1, 0),
SOC_SINGLE("SPUS ASRC0 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(0), 1, 0),
SOC_SINGLE("SPUS ASRC1 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(1), 1, 0),
SOC_SINGLE("SPUS ASRC2 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(2), 1, 0),
SOC_SINGLE("SPUS ASRC3 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(3), 1, 0),
SOC_SINGLE("SPUS ASRC4 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(4), 1, 0),
SOC_SINGLE("SPUS ASRC5 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(5), 1, 0),
SOC_SINGLE("SPUS ASRC6 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(6), 1, 0),
SOC_SINGLE("SPUS ASRC7 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(7), 1, 0),
SOC_SINGLE("SPUS ASRC8 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(8), 1, 0),
SOC_SINGLE("SPUS ASRC9 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(9), 1, 0),
SOC_SINGLE("SPUS ASRC10 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(10), 1, 0),
SOC_SINGLE("SPUS ASRC11 Dummy Start", ABOX_SPUS_LATENCY_CTRL0,
ABOX_RDMA_ASRC_DUMMY_START_L(11), 1, 0),
SOC_SINGLE("SPUS ASRC0 Start Num", ABOX_SPUS_LATENCY_CTRL1,
ABOX_RDMA_START_ASRC_NUM_L(0), 32, 0),
SOC_SINGLE("SPUS ASRC1 Start Num", ABOX_SPUS_LATENCY_CTRL1,
ABOX_RDMA_START_ASRC_NUM_L(1), 32, 0),
SOC_SINGLE("SPUS ASRC2 Start Num", ABOX_SPUS_LATENCY_CTRL1,
ABOX_RDMA_START_ASRC_NUM_L(2), 32, 0),
SOC_SINGLE("SPUS ASRC3 Start Num", ABOX_SPUS_LATENCY_CTRL1,
ABOX_RDMA_START_ASRC_NUM_L(3), 32, 0),
SOC_SINGLE("SPUS ASRC4 Start Num", ABOX_SPUS_LATENCY_CTRL2,
ABOX_RDMA_START_ASRC_NUM_L(4), 32, 0),
SOC_SINGLE("SPUS ASRC5 Start Num", ABOX_SPUS_LATENCY_CTRL2,
ABOX_RDMA_START_ASRC_NUM_L(5), 32, 0),
SOC_SINGLE("SPUS ASRC6 Start Num", ABOX_SPUS_LATENCY_CTRL2,
ABOX_RDMA_START_ASRC_NUM_L(6), 32, 0),
SOC_SINGLE("SPUS ASRC7 Start Num", ABOX_SPUS_LATENCY_CTRL2,
ABOX_RDMA_START_ASRC_NUM_L(7), 32, 0),
SOC_SINGLE("SPUS ASRC8 Start Num", ABOX_SPUS_LATENCY_CTRL3,
ABOX_RDMA_START_ASRC_NUM_L(8), 32, 0),
SOC_SINGLE("SPUS ASRC9 Start Num", ABOX_SPUS_LATENCY_CTRL3,
ABOX_RDMA_START_ASRC_NUM_L(9), 32, 0),
SOC_SINGLE("SPUS ASRC10 Start Num", ABOX_SPUS_LATENCY_CTRL3,
ABOX_RDMA_START_ASRC_NUM_L(10), 32, 0),
SOC_SINGLE("SPUS ASRC11 Start Num", ABOX_SPUS_LATENCY_CTRL3,
ABOX_RDMA_START_ASRC_NUM_L(11), 32, 0),
};
static const struct snd_kcontrol_new spus_asrc_controls[] = {
SOC_SINGLE_EXT("SPUS ASRC0", ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_ASRC_L(0), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC1", ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_ASRC_L(1), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC2", ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_ASRC_L(2), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC3", ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_ASRC_L(3), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC4", ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_ASRC_L(4), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC5", ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_ASRC_L(5), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC6", ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_ASRC_L(6), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC7", ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_ASRC_L(7), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC8", ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_ASRC_L(8), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC9", ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_ASRC_L(9), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC10", ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_ASRC_L(10), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
SOC_SINGLE_EXT("SPUS ASRC11", ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_ASRC_L(11), 1, 0,
snd_soc_get_volsw, spus_asrc_enable_put),
};
static const struct snd_kcontrol_new spum_asrc_controls[] = {
SOC_SINGLE_EXT("SPUM ASRC0", ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_ASRC_L(0), 1, 0,
snd_soc_get_volsw, spum_asrc_enable_put),
SOC_SINGLE_EXT("SPUM ASRC1", ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_ASRC_L(1), 1, 0,
snd_soc_get_volsw, spum_asrc_enable_put),
SOC_SINGLE_EXT("SPUM ASRC2", ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_ASRC_L(2), 1, 0,
snd_soc_get_volsw, spum_asrc_enable_put),
SOC_SINGLE_EXT("SPUM ASRC3", ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_ASRC_L(3), 1, 0,
snd_soc_get_volsw, spum_asrc_enable_put),
SOC_SINGLE_EXT("SPUM ASRC4", ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_ASRC_L(4), 1, 0,
snd_soc_get_volsw, spum_asrc_enable_put),
};
static const struct snd_kcontrol_new spus_asrc_id_controls[] = {
SOC_SINGLE("SPUS ASRC0 ID", ABOX_SPUS_CTRL4,
ABOX_SRC_ASRC_ID_L(0), 11, 0),
SOC_SINGLE("SPUS ASRC1 ID", ABOX_SPUS_CTRL4,
ABOX_SRC_ASRC_ID_L(1), 11, 0),
SOC_SINGLE("SPUS ASRC2 ID", ABOX_SPUS_CTRL4,
ABOX_SRC_ASRC_ID_L(2), 11, 0),
SOC_SINGLE("SPUS ASRC3 ID", ABOX_SPUS_CTRL4,
ABOX_SRC_ASRC_ID_L(3), 11, 0),
SOC_SINGLE("SPUS ASRC4 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(4), 11, 0),
SOC_SINGLE("SPUS ASRC5 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(5), 11, 0),
SOC_SINGLE("SPUS ASRC6 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(6), 11, 0),
SOC_SINGLE("SPUS ASRC7 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(7), 11, 0),
SOC_SINGLE("SPUS ASRC8 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(8), 11, 0),
SOC_SINGLE("SPUS ASRC9 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(9), 11, 0),
SOC_SINGLE("SPUS ASRC10 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(10), 11, 0),
SOC_SINGLE("SPUS ASRC11 ID", ABOX_SPUS_CTRL5,
ABOX_SRC_ASRC_ID_L(11), 11, 0),
};
static const struct snd_kcontrol_new spum_asrc_id_controls[] = {
SOC_SINGLE("SPUM ASRC0 ID", ABOX_SPUM_CTRL4,
ABOX_NSRC_ASRC_ID_L(0), 7, 0),
SOC_SINGLE("SPUM ASRC1 ID", ABOX_SPUM_CTRL4,
ABOX_NSRC_ASRC_ID_L(1), 7, 0),
SOC_SINGLE("SPUM ASRC2 ID", ABOX_SPUM_CTRL4,
ABOX_NSRC_ASRC_ID_L(2), 7, 0),
SOC_SINGLE("SPUM ASRC3 ID", ABOX_SPUM_CTRL4,
ABOX_NSRC_ASRC_ID_L(3), 7, 0),
SOC_SINGLE("SPUM ASRC4 ID", ABOX_SPUM_CTRL4,
ABOX_NSRC_ASRC_ID_L(4), 7, 0),
};
static const struct snd_kcontrol_new spus_asrc_apf_coef_controls[] = {
SOC_SINGLE_EXT("SPUS ASRC0 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
0, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC1 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
1, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC2 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
2, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC3 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
3, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC4 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
4, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC5 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
5, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC6 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
6, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC7 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
7, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC8 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
8, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC9 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
9, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC10 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
10, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUS ASRC11 APF COEF", SNDRV_PCM_STREAM_PLAYBACK,
11, 1, 0, asrc_apf_coef_get, asrc_apf_coef_put),
};
static const struct snd_kcontrol_new spum_asrc_apf_coef_controls[] = {
SOC_SINGLE_EXT("SPUM ASRC0 APF COEF", SNDRV_PCM_STREAM_CAPTURE, 0, 1, 0,
asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUM ASRC1 APF COEF", SNDRV_PCM_STREAM_CAPTURE, 1, 1, 0,
asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUM ASRC2 APF COEF", SNDRV_PCM_STREAM_CAPTURE, 2, 1, 0,
asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUM ASRC3 APF COEF", SNDRV_PCM_STREAM_CAPTURE, 3, 1, 0,
asrc_apf_coef_get, asrc_apf_coef_put),
SOC_SINGLE_EXT("SPUM ASRC4 APF COEF", SNDRV_PCM_STREAM_CAPTURE, 4, 1, 0,
asrc_apf_coef_get, asrc_apf_coef_put),
};
static const char * const asrc_source_enum_texts[] = {
"CP",
"UAIF0",
"UAIF1",
"UAIF2",
"UAIF3",
"UAIF4",
"UAIF5",
"UAIF6",
"USB",
"BCLK_CP",
"BCLK_SPDY",
"ABOX",
};
static const unsigned int asrc_source_enum_values[] = {
TICK_CP,
TICK_UAIF0,
TICK_UAIF1,
TICK_UAIF2,
TICK_UAIF3,
TICK_UAIF4,
TICK_UAIF5,
TICK_UAIF6,
TICK_USB,
TICK_BCLK_CP,
TICK_BCLK_SPDY,
TICK_SYNC,
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc0_os_enum, 0, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc1_os_enum, 1, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc2_os_enum, 2, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc3_os_enum, 3, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc4_os_enum, 4, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc5_os_enum, 5, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc6_os_enum, 6, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc7_os_enum, 7, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc8_os_enum, 8, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc9_os_enum, 9, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc10_os_enum, 10, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc11_os_enum, 11, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static const struct snd_kcontrol_new spus_asrc_os_controls[] = {
SOC_VALUE_ENUM_EXT("SPUS ASRC0 OS", spus_asrc0_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC1 OS", spus_asrc1_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC2 OS", spus_asrc2_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC3 OS", spus_asrc3_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC4 OS", spus_asrc4_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC5 OS", spus_asrc5_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC6 OS", spus_asrc6_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC7 OS", spus_asrc7_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC8 OS", spus_asrc8_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC9 OS", spus_asrc9_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC10 OS", spus_asrc10_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC11 OS", spus_asrc11_os_enum,
spus_asrc_os_get, spus_asrc_os_put),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc0_is_enum, 0, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc1_is_enum, 1, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc2_is_enum, 2, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc3_is_enum, 3, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc4_is_enum, 4, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc5_is_enum, 5, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc6_is_enum, 6, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc7_is_enum, 7, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc8_is_enum, 8, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc9_is_enum, 9, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc10_is_enum, 10, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spus_asrc11_is_enum, 11, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static const struct snd_kcontrol_new spus_asrc_is_controls[] = {
SOC_VALUE_ENUM_EXT("SPUS ASRC0 IS", spus_asrc0_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC1 IS", spus_asrc1_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC2 IS", spus_asrc2_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC3 IS", spus_asrc3_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC4 IS", spus_asrc4_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC5 IS", spus_asrc5_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC6 IS", spus_asrc6_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC7 IS", spus_asrc7_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC8 IS", spus_asrc8_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC9 IS", spus_asrc9_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC10 IS", spus_asrc10_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUS ASRC11 IS", spus_asrc11_is_enum,
spus_asrc_is_get, spus_asrc_is_put),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc0_os_enum, 0, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc1_os_enum, 1, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc2_os_enum, 2, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc3_os_enum, 3, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc4_os_enum, 4, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static const struct snd_kcontrol_new spum_asrc_os_controls[] = {
SOC_VALUE_ENUM_EXT("SPUM ASRC0 OS", spum_asrc0_os_enum,
spum_asrc_os_get, spum_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC1 OS", spum_asrc1_os_enum,
spum_asrc_os_get, spum_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC2 OS", spum_asrc2_os_enum,
spum_asrc_os_get, spum_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC3 OS", spum_asrc3_os_enum,
spum_asrc_os_get, spum_asrc_os_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC4 OS", spum_asrc4_os_enum,
spum_asrc_os_get, spum_asrc_os_put),
};
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc0_is_enum, 0, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc1_is_enum, 1, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc2_is_enum, 2, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc3_is_enum, 3, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static SOC_VALUE_ENUM_SINGLE_DECL(spum_asrc4_is_enum, 4, 0, 0,
asrc_source_enum_texts, asrc_source_enum_values);
static const struct snd_kcontrol_new spum_asrc_is_controls[] = {
SOC_VALUE_ENUM_EXT("SPUM ASRC0 IS", spum_asrc0_is_enum,
spum_asrc_is_get, spum_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC1 IS", spum_asrc1_is_enum,
spum_asrc_is_get, spum_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC2 IS", spum_asrc2_is_enum,
spum_asrc_is_get, spum_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC3 IS", spum_asrc3_is_enum,
spum_asrc_is_get, spum_asrc_is_put),
SOC_VALUE_ENUM_EXT("SPUM ASRC4 IS", spum_asrc4_is_enum,
spum_asrc_is_get, spum_asrc_is_put),
};
struct snd_soc_dapm_widget *spus_asrc_widgets[ARRAY_SIZE(spus_asrc_controls)];
struct snd_soc_dapm_widget *spum_asrc_widgets[ARRAY_SIZE(spum_asrc_controls)];
static void asrc_cache_widget(struct snd_soc_dapm_widget *w,
int idx, int stream)
{
struct device *dev = w->dapm->dev;
abox_dbg(dev, "%s(%s, %d, %d)\n", __func__, w->name, idx, stream);
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
spus_asrc_widgets[idx] = w;
else
spum_asrc_widgets[idx] = w;
}
static struct snd_soc_dapm_widget *asrc_find_widget(
struct snd_soc_card *card, int idx, int stream)
{
struct device *dev = card->dev;
struct snd_soc_dapm_widget *w;
const char *name;
abox_dbg(dev, "%s(%s, %d, %d)\n", __func__, card->name, idx, stream);
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
name = spus_asrc_controls[idx].name;
else
name = spum_asrc_controls[idx].name;
list_for_each_entry(w, &card->widgets, list) {
struct snd_soc_component *cmpnt = w->dapm->component;
const char *name_prefix = cmpnt ? cmpnt->name_prefix : NULL;
size_t prefix_len = name_prefix ? strlen(name_prefix) + 1 : 0;
const char *w_name = w->name + prefix_len;
if (!strcmp(name, w_name))
return w;
}
return NULL;
}
static struct snd_soc_dapm_widget *asrc_get_widget(
struct snd_soc_component *cmpnt, int idx, int stream)
{
struct snd_soc_dapm_widget *w;
struct device *dev;
if (idx < 0)
return NULL;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
w = spus_asrc_widgets[idx];
else
w = spum_asrc_widgets[idx];
if (!w) {
w = asrc_find_widget(cmpnt->card, idx, stream);
asrc_cache_widget(w, idx, stream);
}
dev = w->dapm->dev;
abox_dbg(dev, "%s(%d, %d): %s\n", __func__, idx, stream, w->name);
return w;
}
static bool is_direct_connection(struct snd_soc_component *cmpnt,
enum abox_dai dai)
{
unsigned int val = 0;
bool ret;
switch (dai) {
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL2, &val);
val &= ABOX_NSRC_CONNECTION_TYPE_MASK(dai - ABOX_NSRC0);
val >>= ABOX_NSRC_CONNECTION_TYPE_L(dai - ABOX_NSRC0);
ret = !val;
break;
default:
ret = false;
break;
}
return ret;
}
static enum abox_dai get_sink_dai_id(struct abox_data *data, enum abox_dai id);
static enum abox_dai get_source_dai_id(struct abox_data *data, enum abox_dai id)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val = 0;
enum abox_dai _id, ret = ABOX_NONE;
switch (id) {
case ABOX_WDMA0:
case ABOX_WDMA0_BE:
ret = ABOX_NSRC0;
break;
case ABOX_WDMA1:
case ABOX_WDMA1_BE:
ret = ABOX_NSRC1;
break;
case ABOX_WDMA2:
case ABOX_WDMA2_BE:
ret = ABOX_NSRC2;
break;
case ABOX_WDMA3:
case ABOX_WDMA3_BE:
ret = ABOX_NSRC3;
break;
case ABOX_WDMA4:
case ABOX_WDMA4_BE:
ret = ABOX_NSRC4;
break;
case ABOX_WDMA5:
case ABOX_WDMA5_BE:
ret = ABOX_NSRC5;
break;
case ABOX_WDMA6:
case ABOX_WDMA6_BE:
ret = ABOX_NSRC6;
break;
case ABOX_WDMA7:
case ABOX_WDMA7_BE:
ret = ABOX_NSRC7;
break;
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL0, &val);
val &= ABOX_ROUTE_UAIF_SPK_MASK(id - ABOX_UAIF0);
val >>= ABOX_ROUTE_UAIF_SPK_L(id - ABOX_UAIF0);
switch (val) {
case 0x1:
ret = ABOX_SIFS0;
break;
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x3:
ret = ABOX_SIFS2;
break;
case 0x4:
ret = ABOX_SIFS3;
break;
case 0x5:
ret = ABOX_SIFS4;
break;
case 0x6:
ret = ABOX_SIFS5;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_DSIF:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL0, &val);
val &= ABOX_ROUTE_DSIF_MASK;
val >>= ABOX_ROUTE_DSIF_L;
switch (val) {
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x3:
ret = ABOX_SIFS2;
break;
case 0x4:
ret = ABOX_SIFS3;
break;
case 0x5:
ret = ABOX_SIFS4;
break;
case 0x6:
ret = ABOX_SIFS5;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_SIFS0:
case ABOX_SIFS1:
case ABOX_SIFS2:
case ABOX_SIFS3:
case ABOX_SIFS4:
case ABOX_SIFS5:
for (_id = ABOX_RDMA0; _id <= ABOX_RDMA11; _id++) {
if (get_sink_dai_id(data, _id) == id) {
ret = _id;
break;
}
}
break;
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL1, &val);
val &= ABOX_ROUTE_NSRC_MASK(id - ABOX_NSRC0);
val >>= ABOX_ROUTE_NSRC_L(id - ABOX_NSRC0);
switch (val) {
case 0x1:
ret = ABOX_SIFS0;
break;
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x3:
ret = ABOX_SIFS2;
break;
case 0x4:
ret = ABOX_SIFS3;
break;
case 0x5:
ret = ABOX_SIFS4;
break;
case 0x6:
ret = ABOX_SIFS5;
break;
case 0x8:
ret = ABOX_UAIF0;
break;
case 0x9:
ret = ABOX_UAIF1;
break;
case 0xa:
ret = ABOX_UAIF2;
break;
case 0xb:
ret = ABOX_UAIF3;
break;
case 0xc:
ret = ABOX_UAIF4;
break;
case 0xd:
ret = ABOX_UAIF5;
break;
case 0xe:
ret = ABOX_UAIF6;
break;
case 0x10:
ret = ABOX_BI_PDI0;
break;
case 0x11:
ret = ABOX_BI_PDI1;
break;
case 0x12:
ret = ABOX_BI_PDI2;
break;
case 0x13:
ret = ABOX_BI_PDI3;
break;
case 0x14:
ret = ABOX_BI_PDI4;
break;
case 0x15:
ret = ABOX_BI_PDI5;
break;
case 0x16:
ret = ABOX_BI_PDI6;
break;
case 0x17:
ret = ABOX_BI_PDI7;
break;
case 0x18:
ret = ABOX_RX_PDI0;
break;
case 0x19:
ret = ABOX_RX_PDI1;
break;
case 0x1f:
ret = ABOX_SPDY;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_RDMA0:
case ABOX_RDMA1:
case ABOX_RDMA2:
case ABOX_RDMA3:
case ABOX_RDMA0_BE:
case ABOX_RDMA1_BE:
case ABOX_RDMA2_BE:
case ABOX_RDMA3_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC0, &val);
val &= ABOX_FUNC_CHAIN_SRC_IN_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_IN_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFSM;
break;
case 0x3:
ret = ABOX_SIFST;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_RDMA4:
case ABOX_RDMA5:
case ABOX_RDMA6:
case ABOX_RDMA7:
case ABOX_RDMA4_BE:
case ABOX_RDMA5_BE:
case ABOX_RDMA6_BE:
case ABOX_RDMA7_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC1, &val);
val &= ABOX_FUNC_CHAIN_SRC_IN_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_IN_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFSM;
break;
case 0x3:
ret = ABOX_SIFST;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_RDMA8:
case ABOX_RDMA9:
case ABOX_RDMA10:
case ABOX_RDMA11:
case ABOX_RDMA8_BE:
case ABOX_RDMA9_BE:
case ABOX_RDMA10_BE:
case ABOX_RDMA11_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC2, &val);
val &= ABOX_FUNC_CHAIN_SRC_IN_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_IN_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFSM;
break;
case 0x3:
ret = ABOX_SIFST;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_SIFSM:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL0, &val);
val &= ABOX_ROUTE_SPUSM_MASK;
val >>= ABOX_ROUTE_SPUSM_L;
switch (val) {
case 0x8:
case 0x9:
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0xe:
ret = ABOX_UAIF0 + val - 0x8;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
ret = ABOX_BI_PDI0 + val - 0x10;
break;
case 0x18:
case 0x19:
ret = ABOX_RX_PDI0 + val - 0x18;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_SIFST:
snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL2, &val);
val &= ABOX_ROUTE_SPUST_MASK;
val >>= ABOX_ROUTE_SPUST_L;
switch (val) {
case 0x8:
case 0x9:
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0xe:
ret = ABOX_UAIF0 + val - 0x8;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
ret = ABOX_BI_PDI0 + val - 0x10;
break;
case 0x18:
case 0x19:
ret = ABOX_RX_PDI0 + val - 0x18;
break;
default:
ret = ABOX_NONE;
break;
}
break;
default:
ret = ABOX_NONE;
break;
}
return ret;
}
static enum abox_dai get_sink_dai_id(struct abox_data *data, enum abox_dai id)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int val = 0;
enum abox_dai _id, ret = ABOX_NONE;
switch (id) {
case ABOX_RDMA0:
case ABOX_RDMA1:
case ABOX_RDMA2:
case ABOX_RDMA3:
case ABOX_RDMA0_BE:
case ABOX_RDMA1_BE:
case ABOX_RDMA2_BE:
case ABOX_RDMA3_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC0, &val);
val &= ABOX_FUNC_CHAIN_SRC_OUT_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_OUT_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFS0;
break;
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x4:
ret = ABOX_SIFS2;
break;
case 0x6:
ret = ABOX_SIFS3;
break;
case 0x8:
ret = ABOX_SIFS4;
break;
case 0xa:
ret = ABOX_SIFS5;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_RDMA4:
case ABOX_RDMA5:
case ABOX_RDMA6:
case ABOX_RDMA7:
case ABOX_RDMA4_BE:
case ABOX_RDMA5_BE:
case ABOX_RDMA6_BE:
case ABOX_RDMA7_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC1, &val);
val &= ABOX_FUNC_CHAIN_SRC_OUT_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_OUT_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFS0;
break;
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x4:
ret = ABOX_SIFS2;
break;
case 0x6:
ret = ABOX_SIFS3;
break;
case 0x8:
ret = ABOX_SIFS4;
break;
case 0xa:
ret = ABOX_SIFS5;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_RDMA8:
case ABOX_RDMA9:
case ABOX_RDMA10:
case ABOX_RDMA11:
case ABOX_RDMA8_BE:
case ABOX_RDMA9_BE:
case ABOX_RDMA10_BE:
case ABOX_RDMA11_BE:
snd_soc_component_read(cmpnt, ABOX_SPUS_CTRL_FC2, &val);
val &= ABOX_FUNC_CHAIN_SRC_OUT_MASK(id - ABOX_RDMA0);
val >>= ABOX_FUNC_CHAIN_SRC_OUT_L(id - ABOX_RDMA0);
switch (val) {
case 0x1:
ret = ABOX_SIFS0;
break;
case 0x2:
ret = ABOX_SIFS1;
break;
case 0x4:
ret = ABOX_SIFS2;
break;
case 0x6:
ret = ABOX_SIFS3;
break;
case 0x8:
ret = ABOX_SIFS4;
break;
case 0xa:
ret = ABOX_SIFS5;
break;
default:
ret = ABOX_NONE;
break;
}
break;
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
case ABOX_SPDY:
for (_id = ABOX_NSRC0; _id <= ABOX_NSRC5; _id++) {
if (get_source_dai_id(data, _id) == id &&
is_direct_connection(cmpnt, _id)) {
ret = _id;
break;
}
}
break;
case ABOX_SIFS0:
case ABOX_SIFS1:
case ABOX_SIFS2:
case ABOX_SIFS3:
case ABOX_SIFS4:
case ABOX_SIFS5:
for (_id = ABOX_UAIF0; _id <= ABOX_DSIF; _id++) {
if (get_source_dai_id(data, _id) == id) {
ret = _id;
break;
}
}
if (ret != ABOX_NONE)
break;
for (_id = ABOX_NSRC0; _id <= ABOX_NSRC5; _id++) {
if (get_source_dai_id(data, _id) == id &&
is_direct_connection(cmpnt, _id)) {
ret = _id;
break;
}
}
break;
case ABOX_NSRC0:
ret = ABOX_WDMA0;
break;
case ABOX_NSRC1:
ret = ABOX_WDMA1;
break;
case ABOX_NSRC2:
ret = ABOX_WDMA2;
break;
case ABOX_NSRC3:
ret = ABOX_WDMA3;
break;
case ABOX_NSRC4:
ret = ABOX_WDMA4;
break;
case ABOX_NSRC5:
ret = ABOX_WDMA5;
break;
case ABOX_NSRC6:
ret = ABOX_WDMA6;
break;
case ABOX_NSRC7:
ret = ABOX_WDMA7;
break;
default:
ret = ABOX_NONE;
break;
}
return ret;
}
static struct snd_soc_dai *find_dai(struct snd_soc_card *card, enum abox_dai id)
{
struct snd_soc_pcm_runtime *rtd;
list_for_each_entry(rtd, &card->rtd_list, list) {
if (rtd->cpu_dai->id == id)
return rtd->cpu_dai;
}
return NULL;
}
static int get_configmsg(enum abox_dai id, enum ABOX_CONFIGMSG *rate,
enum ABOX_CONFIGMSG *format)
{
int ret = 0;
switch (id) {
case ABOX_SIFS0:
*rate = SET_SIFS0_RATE;
*format = SET_SIFS0_FORMAT;
break;
case ABOX_SIFS1:
*rate = SET_SIFS1_RATE;
*format = SET_SIFS1_FORMAT;
break;
case ABOX_SIFS2:
*rate = SET_SIFS2_RATE;
*format = SET_SIFS2_FORMAT;
break;
case ABOX_SIFS3:
*rate = SET_SIFS3_RATE;
*format = SET_SIFS3_FORMAT;
break;
case ABOX_SIFS4:
*rate = SET_SIFS4_RATE;
*format = SET_SIFS4_FORMAT;
break;
case ABOX_SIFS5:
*rate = SET_SIFS5_RATE;
*format = SET_SIFS5_FORMAT;
break;
case ABOX_NSRC0:
*rate = SET_SIFM0_RATE;
*format = SET_SIFM0_FORMAT;
break;
case ABOX_NSRC1:
*rate = SET_SIFM1_RATE;
*format = SET_SIFM1_FORMAT;
break;
case ABOX_NSRC2:
*rate = SET_SIFM2_RATE;
*format = SET_SIFM2_FORMAT;
break;
case ABOX_NSRC3:
*rate = SET_SIFM3_RATE;
*format = SET_SIFM3_FORMAT;
break;
case ABOX_NSRC4:
*rate = SET_SIFM4_RATE;
*format = SET_SIFM4_FORMAT;
break;
case ABOX_NSRC5:
*rate = SET_SIFM5_RATE;
*format = SET_SIFM5_FORMAT;
break;
case ABOX_NSRC6:
*rate = SET_SIFM6_RATE;
*format = SET_SIFM6_FORMAT;
break;
case ABOX_NSRC7:
*rate = SET_SIFM7_RATE;
*format = SET_SIFM7_FORMAT;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int set_sif_params(struct abox_data *data, enum abox_dai id,
const struct snd_pcm_hw_params *params)
{
struct device *adev = data->dev;
enum ABOX_CONFIGMSG msg_rate, msg_format;
unsigned int rate, channels;
snd_pcm_format_t format;
int ret = 0;
ret = get_configmsg(id, &msg_rate, &msg_format);
if (ret < 0) {
abox_err(adev, "can't set sif params: %d\n", ret);
return ret;
}
rate = params_rate(params);
format = params_format(params);
channels = params_channels(params);
if (get_sif_rate(data, msg_rate) != rate) {
set_sif_rate(data, msg_rate, rate);
rate_put_ipc(adev, rate, msg_rate);
}
if (get_sif_channels(data, msg_format) != channels ||
get_sif_format(data, msg_format) != format) {
set_sif_format(data, msg_format, format);
set_sif_channels(data, msg_format, channels);
format_put_ipc(adev, format, channels, msg_format);
}
return ret;
}
static unsigned int sifsx_cnt_val(unsigned long aclk, unsigned int rate,
unsigned int physical_width, unsigned int channels)
{
static const int correction;
unsigned int n, d;
/* k = n / d */
d = channels * rate;
n = 2 * (32 / physical_width);
return DIV_ROUND_CLOSEST_ULL(aclk * n, d) - 1 + correction;
}
static int set_cnt_val(struct abox_data *data, struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct device *dev = dai->dev;
struct regmap *regmap = data->regmap;
enum abox_dai id = dai->id;
int idx = id - ABOX_SIFS0;
unsigned int rate = params_rate(params);
unsigned int width = params_width(params);
unsigned int pwidth = params_physical_width(params);
unsigned int channels = params_channels(params);
unsigned long clk;
unsigned int cnt_val;
int ret = 0;
ret = abox_register_bclk_usage(dev, data, id, rate, channels, width);
if (ret < 0)
abox_err(dev, "Unable to register bclk usage: %d\n", ret);
clk = clk_get_rate(data->clk_cnt);
cnt_val = sifsx_cnt_val(clk, rate, pwidth, channels);
abox_info(dev, "%s[%#x](%ubit %uchannel %uHz at %luHz): %u\n",
__func__, id, width, channels, rate, clk, cnt_val);
ret = regmap_update_bits(regmap, ABOX_SPUS_CTRL_SIFS_CNT(idx),
ABOX_SIFS_CNT_VAL_MASK(idx),
cnt_val << ABOX_SIFS_CNT_VAL_L(idx));
return ret;
}
static int hw_params_fixup(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct device *dev = dai->dev;
struct abox_data *data = abox_get_data(dev);
enum ABOX_CONFIGMSG msg_rate, msg_format;
unsigned int rate, channels, width;
snd_pcm_format_t format;
int ret = 0;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
ret = get_configmsg(dai->id, &msg_rate, &msg_format);
if (ret < 0)
return ret;
rate = get_sif_rate(data, msg_rate);
channels = get_sif_channels(data, msg_format);
width = get_sif_width(data, msg_format);
format = get_sif_format(data, msg_format);
if (rate)
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = rate;
if (channels)
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min =
channels;
if (format) {
struct snd_mask *mask;
mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_none(mask);
snd_mask_set(mask, format);
}
if (rate || channels || format)
abox_dbg(dev, "%s: %d bit, %u ch, %uHz\n", dai->name,
width, channels, rate);
return ret;
}
static int sifs_hw_params_fixup(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct snd_soc_component *cmpnt = dai->component;
struct device *dev = dai->dev;
struct abox_data *data = dev_get_drvdata(dev);
enum abox_dai id = dai->id;
enum abox_dai _id;
struct snd_soc_dai *_dai;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
_id = get_sink_dai_id(data, id);
switch (_id) {
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
case ABOX_DSIF:
_dai = find_dai(cmpnt->card, _id);
abox_if_hw_params_fixup(_dai, params);
break;
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
hw_params_fixup(dai, params);
set_cnt_val(data, dai, params);
break;
default:
abox_err(dev, "%s: invalid sink dai:%#x\n", dai->name, _id);
break;
}
return set_sif_params(data, id, params);
}
static int sifm_hw_params_fixup(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct snd_soc_component *cmpnt = dai->component;
struct device *dev = dai->dev;
struct abox_data *data = dev_get_drvdata(dev);
enum abox_dai id = dai->id;
enum abox_dai _id;
struct snd_soc_dai *_dai;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
_id = get_source_dai_id(data, id);
switch (_id) {
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
case ABOX_DSIF:
case ABOX_SPDY:
_dai = find_dai(cmpnt->card, _id);
abox_if_hw_params_fixup(_dai, params);
break;
case ABOX_SIFS0:
case ABOX_SIFS1:
case ABOX_SIFS2:
case ABOX_SIFS3:
case ABOX_SIFS4:
case ABOX_SIFS5:
_dai = find_dai(cmpnt->card, _id);
sifs_hw_params_fixup(_dai, params);
break;
default:
abox_err(dev, "%s: invalid source dai:%#x\n", dai->name, _id);
break;
}
return set_sif_params(data, id, params);
}
static int rdma_hw_params_fixup(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct snd_soc_component *cmpnt = dai->component;
struct abox_dma_data *data = snd_soc_dai_get_drvdata(dai);
struct device *dev = dai->dev;
enum abox_dai id = dai->id;
enum abox_dai _id;
struct snd_soc_dai *_dai;
int ret;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
_id = get_sink_dai_id(data->abox_data, id);
switch (_id) {
case ABOX_SIFS0:
case ABOX_SIFS1:
case ABOX_SIFS2:
case ABOX_SIFS3:
case ABOX_SIFS4:
case ABOX_SIFS5:
_dai = find_dai(cmpnt->card, _id);
ret = sifs_hw_params_fixup(_dai, params);
abox_dma_set_dst_bit_width(dev, params_width(params));
break;
default:
abox_err(dev, "%s: invalid sifs dai:%#x\n", dai->name, _id);
ret = -EINVAL;
break;
}
return ret;
}
static int wdma_hw_params_fixup(struct snd_soc_dai *dai,
struct snd_pcm_hw_params *params)
{
struct snd_soc_component *cmpnt = dai->component;
struct abox_dma_data *data = snd_soc_dai_get_drvdata(dai);
struct device *dev = dai->dev;
enum abox_dai id = dai->id;
enum abox_dai _id;
struct snd_soc_dai *_dai;
int ret;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
_id = get_source_dai_id(data->abox_data, id);
switch (_id) {
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
_dai = find_dai(cmpnt->card, _id);
ret = sifm_hw_params_fixup(_dai, params);
abox_dma_set_dst_bit_width(dev, params_width(params));
break;
default:
abox_err(dev, "%s: invalid sifs dai:%#x\n", dai->name, _id);
ret = -EINVAL;
break;
}
return ret;
}
static int rdma_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_hw_params _params = *params;
rdma_hw_params_fixup(rtd->cpu_dai, &_params);
return abox_dma_hw_params_fixup(rtd->cpu_dai->dev, params);
}
static int wdma_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_hw_params _params = *params;
wdma_hw_params_fixup(rtd->cpu_dai, &_params);
return abox_dma_hw_params_fixup(rtd->cpu_dai->dev, params);
}
unsigned int abox_cmpnt_sif_get_dst_format(struct abox_data *data,
int stream, int id)
{
static const enum ABOX_CONFIGMSG configmsg_p[] = {
SET_SIFS0_FORMAT, SET_SIFS1_FORMAT, SET_SIFS2_FORMAT,
SET_SIFS3_FORMAT, SET_SIFS4_FORMAT, SET_SIFS5_FORMAT,
};
static const enum ABOX_CONFIGMSG configmsg_c[] = {
SET_SIFM0_FORMAT, SET_SIFM1_FORMAT, SET_SIFM2_FORMAT,
SET_SIFM3_FORMAT, SET_SIFM4_FORMAT, SET_SIFM5_FORMAT,
SET_SIFM6_FORMAT, SET_SIFM7_FORMAT,
};
const enum ABOX_CONFIGMSG *configmsg;
unsigned int width, channels, format;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (id >= ARRAY_SIZE(configmsg_p)) {
abox_err(data->dev, "%s(%d, %d): invalid argument\n",
__func__, stream, id);
return -EINVAL;
}
configmsg = configmsg_p;
} else {
if (id >= ARRAY_SIZE(configmsg_c)) {
abox_err(data->dev, "%s(%d, %d): invalid argument\n",
__func__, stream, id);
return -EINVAL;
}
configmsg = configmsg_c;
}
width = get_sif_width(data, configmsg[id]);
channels = get_sif_channels(data, configmsg[id]);
format = abox_get_format(width, channels);
return format;
}
void abox_cmpnt_register_event_notifier(struct abox_data *data,
enum abox_widget w, int (*notify)(void *priv, bool en),
void *priv)
{
struct abox_event_notifier *event_notifier = &data->event_notifier[w];
WRITE_ONCE(event_notifier->priv, priv);
WRITE_ONCE(event_notifier->notify, notify);
}
void abox_cmpnt_unregister_event_notifier(struct abox_data *data,
enum abox_widget w)
{
struct abox_event_notifier *event_notifier = &data->event_notifier[w];
WRITE_ONCE(event_notifier->notify, NULL);
WRITE_ONCE(event_notifier->priv, NULL);
}
static int notify_event(struct abox_data *data, enum abox_widget w, int e)
{
struct abox_event_notifier event_notifier;
bool en;
switch (e) {
case SND_SOC_DAPM_POST_PMU:
case SND_SOC_DAPM_PRE_PMU:
en = true;
break;
case SND_SOC_DAPM_PRE_PMD:
case SND_SOC_DAPM_POST_PMD:
en = false;
break;
default:
return 0;
};
event_notifier = data->event_notifier[w];
if (event_notifier.notify)
return event_notifier.notify(event_notifier.priv, en);
else
return 0;
}
static int spus_in0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN0, e);
}
static int spus_in1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN1, e);
}
static int spus_in2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN2, e);
}
static int spus_in3_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN3, e);
}
static int spus_in4_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN4, e);
}
static int spus_in5_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN5, e);
}
static int spus_in6_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN6, e);
}
static int spus_in7_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN7, e);
}
static int spus_in8_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN8, e);
}
static int spus_in9_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN9, e);
}
static int spus_in10_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN10, e);
}
static int spus_in11_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SPUS_IN11, e);
}
static int sifs0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS0, e);
}
static int sifs1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS1, e);
}
static int sifs2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS2, e);
}
static int sifs3_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS3, e);
}
static int sifs4_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS4, e);
}
static int sifs5_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_SIFS5, e);
}
static int nsrc0_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_NSRC0, e);
}
static int nsrc1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_NSRC1, e);
}
static int nsrc2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_NSRC2, e);
}
static int nsrc3_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_NSRC3, e);
}
static int nsrc4_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
return notify_event(data, ABOX_WIDGET_NSRC4, e);
}
static int asrc_get_idx(struct snd_soc_dapm_widget *w)
{
return w->shift;
}
static const struct snd_kcontrol_new *asrc_get_kcontrol(int idx, int stream)
{
if (idx < 0)
return ERR_PTR(-EINVAL);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (idx < ARRAY_SIZE(spus_asrc_controls))
return &spus_asrc_controls[idx];
else
return ERR_PTR(-EINVAL);
} else {
if (idx < ARRAY_SIZE(spum_asrc_controls))
return &spum_asrc_controls[idx];
else
return ERR_PTR(-EINVAL);
}
}
static const struct snd_kcontrol_new *asrc_get_id_kcontrol(int idx, int stream)
{
if (idx < 0)
return ERR_PTR(-EINVAL);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (idx < ARRAY_SIZE(spus_asrc_id_controls))
return &spus_asrc_id_controls[idx];
else
return ERR_PTR(-EINVAL);
} else {
if (idx < ARRAY_SIZE(spum_asrc_id_controls))
return &spum_asrc_id_controls[idx];
else
return ERR_PTR(-EINVAL);
}
}
static int asrc_get_id(struct snd_soc_component *cmpnt, int idx, int stream)
{
const struct snd_kcontrol_new *kcontrol;
struct soc_mixer_control *mc;
unsigned int reg, mask, val;
int ret;
kcontrol = asrc_get_id_kcontrol(idx, stream);
if (IS_ERR(kcontrol))
return PTR_ERR(kcontrol);
mc = (struct soc_mixer_control *)kcontrol->private_value;
reg = mc->reg;
mask = ((1 << fls(mc->max)) - 1) << mc->shift;
ret = snd_soc_component_read(cmpnt, reg, &val);
if (ret < 0)
return ret;
return (val & mask) >> mc->shift;
}
static bool asrc_get_active(struct snd_soc_component *cmpnt, int idx,
int stream)
{
const struct snd_kcontrol_new *kcontrol;
struct soc_mixer_control *mc;
unsigned int reg, mask, val;
int ret;
kcontrol = asrc_get_kcontrol(idx, stream);
if (IS_ERR(kcontrol))
return false;
mc = (struct soc_mixer_control *)kcontrol->private_value;
reg = mc->reg;
mask = 1 << mc->shift;
ret = snd_soc_component_read(cmpnt, reg, &val);
if (ret < 0)
return false;
return !!(val & mask);
}
static int asrc_get_idx_of_id(struct snd_soc_component *cmpnt, int id,
int stream)
{
int idx;
size_t len;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
len = ARRAY_SIZE(spus_asrc_controls);
else
len = ARRAY_SIZE(spum_asrc_controls);
for (idx = 0; idx < len; idx++) {
if (id == asrc_get_id(cmpnt, idx, stream))
return idx;
}
return -EINVAL;
}
static bool asrc_get_id_active(struct snd_soc_component *cmpnt, int id,
int stream)
{
int idx;
idx = asrc_get_idx_of_id(cmpnt, id, stream);
if (idx < 0)
return false;
return asrc_get_active(cmpnt, idx, stream);
}
static int asrc_put_id(struct snd_soc_component *cmpnt, int idx, int stream,
int id)
{
struct device *dev = cmpnt->dev;
const struct snd_kcontrol_new *kcontrol;
struct soc_mixer_control *mc;
unsigned int reg, mask, val;
abox_dbg(dev, "%s(%d, %d, %d)\n", __func__, idx, stream, id);
kcontrol = asrc_get_id_kcontrol(idx, stream);
if (IS_ERR(kcontrol))
return PTR_ERR(kcontrol);
mc = (struct soc_mixer_control *)kcontrol->private_value;
reg = mc->reg;
mask = ((1 << fls(mc->max)) - 1) << mc->shift;
val = id << mc->shift;
return snd_soc_component_update_bits(cmpnt, reg, mask, val);
}
static int asrc_put_active(struct snd_soc_dapm_widget *w, int stream, int on)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_component *cmpnt = dapm->component;
struct device *dev = cmpnt->dev;
const struct snd_kcontrol_new *kcontrol;
struct soc_mixer_control *mc;
unsigned int reg, mask, val;
abox_dbg(dev, "%s(%s, %d, %d)\n", __func__, w->name, stream, on);
kcontrol = asrc_get_kcontrol(asrc_get_idx(w), stream);
if (IS_ERR(kcontrol))
return PTR_ERR(kcontrol);
abox_info(dev, "%s %s\n", w->name, on ? "on" : "off");
mc = (struct soc_mixer_control *)kcontrol->private_value;
reg = mc->reg;
mask = 1 << mc->shift;
val = !!on << mc->shift;
return snd_soc_component_update_bits(cmpnt, reg, mask, val);
}
static int asrc_exchange_id(struct snd_soc_component *cmpnt, int stream,
int idx1, int idx2)
{
struct device *dev = cmpnt->dev;
int id1 = asrc_get_id(cmpnt, idx1, stream);
int id2 = asrc_get_id(cmpnt, idx2, stream);
int ret;
abox_dbg(dev, "%s(%d, %d, %d)\n", __func__, stream, idx1, idx2);
if (idx1 == idx2)
return 0;
ret = asrc_put_id(cmpnt, idx1, stream, id2);
if (ret < 0)
return ret;
ret = asrc_put_id(cmpnt, idx2, stream, id1);
if (ret < 0)
asrc_put_id(cmpnt, idx1, stream, id1);
return ret;
}
static const int spus_asrc_max_channels[] = {
8, 4, 4, 2, 8, 4, 4, 2,
};
static const int spum_asrc_max_channels[] = {
8, 4, 4, 2,
};
static const int spus_asrc_sorted_id[] = {
3, 7, 2, 6, 1, 5, 0, 4,
};
static const int spum_asrc_sorted_id[] = {
3, 2, 1, 0,
};
static int spus_asrc_channels[] = {
0, 0, 0, 0, 0, 0, 0, 0,
};
static int spum_asrc_channels[] = {
0, 0, 0, 0,
};
static int spus_asrc_lock[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
static int spum_asrc_lock[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
};
int abox_cmpnt_asrc_lock(struct abox_data *data, int stream,
int idx, int id)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
spus_asrc_lock[idx] = id;
else
spum_asrc_lock[idx] = id;
if (id != asrc_get_id(cmpnt, idx, stream)) {
ret = asrc_exchange_id(cmpnt, stream, idx,
asrc_get_idx_of_id(cmpnt, id, stream));
if (ret < 0)
return ret;
ret = asrc_put_active(asrc_get_widget(cmpnt, idx, stream),
stream, 1);
if (ret < 0)
return ret;
}
return ret;
}
static bool asrc_is_lock(int stream, int id)
{
int i;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
for (i = 0; i < ARRAY_SIZE(spus_asrc_lock); i++) {
if (spus_asrc_lock[i] == id)
return true;
}
} else {
for (i = 0; i < ARRAY_SIZE(spum_asrc_lock); i++) {
if (spum_asrc_lock[i] == id)
return true;
}
}
return false;
}
static int asrc_get_lock_id(int stream, int idx)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return spus_asrc_lock[idx];
else
return spum_asrc_lock[idx];
}
static int asrc_get_num(int stream)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return ARRAY_SIZE(spus_asrc_sorted_id);
else
return ARRAY_SIZE(spum_asrc_sorted_id);
}
static int asrc_get_max_channels(int id, int stream)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return spus_asrc_max_channels[id];
else
return spum_asrc_max_channels[id];
}
static int asrc_get_sorted_id(int i, int stream)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return spus_asrc_sorted_id[i];
else
return spum_asrc_sorted_id[i];
}
static int asrc_get_channels(int id, int stream)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return spus_asrc_channels[id];
else
return spum_asrc_channels[id];
}
static void asrc_set_channels(int id, int stream, int channels)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
spus_asrc_channels[id] = channels;
else
spum_asrc_channels[id] = channels;
}
static int asrc_is_avail_id(struct snd_soc_dapm_widget *w, int id,
int stream, int channels)
{
struct snd_soc_component *cmpnt = w->dapm->component;
struct device *dev = cmpnt->dev;
int idx = asrc_get_idx_of_id(cmpnt, id, stream);
struct snd_soc_dapm_widget *w_t = asrc_get_widget(cmpnt, idx, stream);
int ret;
if (asrc_get_max_channels(id, stream) < channels) {
ret = false;
goto out;
}
if (w_t != w && asrc_is_lock(stream, id)) {
ret = false;
goto out;
}
if (w_t != w && asrc_get_id_active(cmpnt, id, stream)) {
ret = false;
goto out;
}
if (id % 2) {
if (asrc_get_id_active(cmpnt, id - 1, stream))
ret = asrc_get_channels(id - 1, stream) <
asrc_get_max_channels(id - 1, stream);
else
ret = true;
} else {
if (channels < asrc_get_max_channels(id, stream))
ret = true;
else
ret = !asrc_get_id_active(cmpnt, id + 1, stream);
}
out:
abox_dbg(dev, "%s(%d, %d, %d): %d\n", __func__,
id, stream, channels, ret);
return ret;
}
static int asrc_assign_id(struct snd_soc_dapm_widget *w, int stream,
unsigned int channels)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_component *cmpnt = dapm->component;
int i, id, ret = -EINVAL;
id = asrc_get_lock_id(stream, asrc_get_idx(w));
if (id >= 0) {
ret = asrc_exchange_id(cmpnt, stream, asrc_get_idx(w),
asrc_get_idx_of_id(cmpnt, id, stream));
if (ret >= 0)
asrc_set_channels(id, stream, channels);
return ret;
}
for (i = 0; i < asrc_get_num(stream); i++) {
id = asrc_get_sorted_id(i, stream);
if (asrc_is_avail_id(w, id, stream, channels)) {
ret = asrc_exchange_id(cmpnt, stream, asrc_get_idx(w),
asrc_get_idx_of_id(cmpnt, id, stream));
if (ret >= 0)
asrc_set_channels(id, stream, channels);
break;
}
}
return ret;
}
static void asrc_release_id(struct snd_soc_dapm_widget *w, int stream)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_component *cmpnt = dapm->component;
int idx = asrc_get_idx(w);
int id = asrc_get_id(cmpnt, idx, stream);
if (id < 0 || id > asrc_get_num(stream))
return;
if (asrc_get_lock_id(stream, idx) >= 0)
return;
asrc_set_channels(id, stream, 0);
asrc_put_active(w, stream, 0);
}
unsigned int abox_cmpnt_asrc_get_dst_format(struct abox_data *data,
int stream, int id)
{
struct snd_soc_component *cmpnt = data->cmpnt;
int width, channels;
unsigned int val;
channels = asrc_get_channels(id, stream);
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_component_read(cmpnt, ABOX_SPUS_ASRC_CTRL(id), &val);
else
snd_soc_component_read(cmpnt, ABOX_SPUM_ASRC_CTRL(id), &val);
width = (val & ABOX_ASRC_BIT_WIDTH_MASK) >> ABOX_ASRC_BIT_WIDTH_L;
return (width << 0x3) | (channels - 1);
}
void abox_cmpnt_asrc_release(struct abox_data *data, int stream, int idx)
{
struct snd_soc_component *cmpnt = data->cmpnt;
abox_dbg(cmpnt->dev, "%s(%d, %d)\n", __func__, stream, idx);
asrc_release_id(asrc_get_widget(cmpnt, idx, stream), stream);
}
static int asrc_find_id(struct snd_soc_dapm_widget *w, int stream)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_component *cmpnt = dapm->component;
return asrc_get_id(cmpnt, asrc_get_idx(w), stream);
}
static int update_bits_async(struct device *dev,
struct snd_soc_component *cmpnt, const char *name,
unsigned int reg, unsigned int mask, unsigned int val)
{
int ret;
abox_dbg(dev, "%s(%s, %#x, %#x, %#x)\n", __func__, name, reg, mask, val);
ret = snd_soc_component_update_bits_async(cmpnt, reg, mask, val);
if (ret < 0)
abox_err(dev, "%s(%s, %#x, %#x, %#x): %d\n", __func__, name, reg,
mask, val, ret);
return ret;
}
static int asrc_update_tick(struct abox_data *data, int stream, int id)
{
static const int tick_table[][3] = {
/* aclk, ticknum, tickdiv */
{600000000, 1, 1},
{400000000, 3, 2},
{300000000, 2, 1},
{200000000, 3, 1},
{150000000, 4, 1},
{100000000, 6, 1},
};
struct snd_soc_component *cmpnt = data->cmpnt;
struct device *dev = cmpnt->dev;
unsigned int reg, mask, val;
enum asrc_tick itick, otick;
int idx = asrc_get_idx_of_id(cmpnt, id, stream);
unsigned long aclk = clk_get_rate(data->clk_bus);
int ticknum = 1, tickdiv = 1;
int i, res, ret = 0;
abox_dbg(dev, "%s(%d, %d, %luHz)\n", __func__, stream, id, aclk);
if (idx < 0) {
abox_err(dev, "%s(%d, %d): invalid idx: %d\n", __func__,
stream, id, idx);
return -EINVAL;
}
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
reg = ABOX_SPUS_ASRC_CTRL(id);
itick = spus_asrc_is[idx];
otick = spus_asrc_os[idx];
} else {
reg = ABOX_SPUM_ASRC_CTRL(id);
itick = spum_asrc_is[idx];
otick = spum_asrc_os[idx];
}
if ((itick == TICK_SYNC) && (otick == TICK_SYNC))
return 0;
res = snd_soc_component_read(cmpnt, reg, &val);
if (res < 0) {
abox_err(dev, "%s: read fail(%#x): %d\n", __func__, reg, res);
ret = res;
}
for (i = 0; i < ARRAY_SIZE(tick_table); i++) {
if (aclk > tick_table[i][0])
break;
ticknum = tick_table[i][1];
tickdiv = tick_table[i][2];
}
mask = ABOX_ASRC_TICKNUM_MASK;
val = ticknum << ABOX_ASRC_TICKNUM_L;
res = update_bits_async(dev, cmpnt, "ticknum", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_TICKDIV_MASK;
val = tickdiv << ABOX_ASRC_TICKDIV_L;
res = update_bits_async(dev, cmpnt, "tickdiv", reg, mask, val);
if (res < 0)
ret = res;
/* Todo: change it to abox_dbg() */
abox_info(dev, "asrc tick(%d, %d) aclk=%luHz: %d, %d\n",
stream, id, aclk, ticknum, tickdiv);
return ret;
}
int abox_cmpnt_update_asrc_tick(struct device *adev)
{
struct device *dev = adev;
struct abox_data *data = dev_get_drvdata(dev);
struct snd_soc_component *cmpnt = data->cmpnt;
int stream, id, res, ret = 0;
if (!cmpnt)
return 0;
abox_dbg(dev, "%s\n", __func__);
for (stream = 0; stream <= SNDRV_PCM_STREAM_LAST; stream++) {
for (id = 0; id < asrc_get_num(stream); id++) {
res = asrc_update_tick(data, stream, id);
if (res < 0)
ret = res;
}
}
snd_soc_component_async_complete(cmpnt);
return ret;
}
static int asrc_config_async(struct abox_data *data, int id, int stream,
enum asrc_tick itick, unsigned int isr,
enum asrc_tick otick, unsigned int osr,
unsigned int s_default, unsigned int width, int apf_coef)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
bool spus = (stream == SNDRV_PCM_STREAM_PLAYBACK);
unsigned int ofactor;
unsigned int reg, mask, val;
struct asrc_ctrl ctrl;
int res, ret = 0;
abox_dbg(dev, "%s(%d, %d, %d, %uHz, %d, %uHz, %u, %ubit, %d)\n",
__func__, id, stream, itick, isr,
otick, osr, s_default, width, apf_coef);
if ((itick == TICK_SYNC) == (otick == TICK_SYNC)) {
abox_err(dev, "%s: itick=%d otick=%d\n", __func__, itick, otick);
return -EINVAL;
}
if (s_default == 0) {
abox_err(dev, "invalid default\n");
return -EINVAL;
}
/* set async side to input side */
ctrl.isr = (itick != TICK_SYNC) ? isr : osr;
ctrl.osr = (itick != TICK_SYNC) ? osr : isr;
ctrl.ovsf = RATIO_8;
ctrl.ifactor = s_default;
ctrl.dcmf = RATIO_8;
ofactor = cal_ofactor(&ctrl);
while (ofactor > ABOX_ASRC_OS_DEFAULT_MASK) {
ctrl.ovsf--;
ofactor = cal_ofactor(&ctrl);
}
if (itick == TICK_SYNC) {
swap(ctrl.isr, ctrl.osr);
swap(ctrl.ovsf, ctrl.dcmf);
swap(ctrl.ifactor, ofactor);
}
abox_dbg(dev, "asrc(%d, %d): %d, %uHz, %d, %uHz, %d, %d, %u, %u, %u, %u\n",
stream, id, itick, ctrl.isr, otick, ctrl.osr,
1 << ctrl.ovsf, 1 << ctrl.dcmf, ctrl.ifactor, ofactor,
is_limit(ctrl.ifactor), os_limit(ofactor));
reg = spus ? ABOX_SPUS_ASRC_CTRL(id) : ABOX_SPUM_ASRC_CTRL(id);
mask = ABOX_ASRC_BIT_WIDTH_MASK;
val = ((width / 8) - 1) << ABOX_ASRC_BIT_WIDTH_L;
res = update_bits_async(dev, cmpnt, "width", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_IS_SYNC_MODE_MASK;
val = (itick != TICK_SYNC) << ABOX_ASRC_IS_SYNC_MODE_L;
res = update_bits_async(dev, cmpnt, "is sync", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OS_SYNC_MODE_MASK;
val = (otick != TICK_SYNC) << ABOX_ASRC_OS_SYNC_MODE_L;
res = update_bits_async(dev, cmpnt, "os sync", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OVSF_RATIO_MASK;
val = ctrl.ovsf << ABOX_ASRC_OVSF_RATIO_L;
res = update_bits_async(dev, cmpnt, "ovsf ratio", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_DCMF_RATIO_MASK;
val = ctrl.dcmf << ABOX_ASRC_DCMF_RATIO_L;
res = update_bits_async(dev, cmpnt, "dcmf ratio", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_IS_SOURCE_SEL_MASK;
val = itick << ABOX_ASRC_IS_SOURCE_SEL_L;
res = update_bits_async(dev, cmpnt, "is source", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OS_SOURCE_SEL_MASK;
val = otick << ABOX_ASRC_OS_SOURCE_SEL_L;
res = update_bits_async(dev, cmpnt, "os source", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_IS_PARA0(id) : ABOX_SPUM_ASRC_IS_PARA0(id);
mask = ABOX_ASRC_IS_DEFAULT_MASK;
val = ctrl.ifactor;
res = update_bits_async(dev, cmpnt, "is default", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_IS_PARA1(id) : ABOX_SPUM_ASRC_IS_PARA1(id);
mask = ABOX_ASRC_IS_TPERIOD_LIMIT_MASK;
val = is_limit(val);
res = update_bits_async(dev, cmpnt, "is tperiod limit", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_OS_PARA0(id) : ABOX_SPUM_ASRC_OS_PARA0(id);
mask = ABOX_ASRC_OS_DEFAULT_MASK;
val = ofactor;
res = update_bits_async(dev, cmpnt, "os default", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_OS_PARA1(id) : ABOX_SPUM_ASRC_OS_PARA1(id);
mask = ABOX_ASRC_OS_TPERIOD_LIMIT_MASK;
val = os_limit(val);
res = update_bits_async(dev, cmpnt, "os tperiod limit", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_FILTER_CTRL(id) :
ABOX_SPUM_ASRC_FILTER_CTRL(id);
mask = ABOX_ASRC_APF_COEF_SEL_MASK;
val = apf_coef << ABOX_ASRC_APF_COEF_SEL_L;
res = update_bits_async(dev, cmpnt, "apf coef sel", reg, mask, val);
if (res < 0)
ret = res;
res = asrc_update_tick(data, stream, id);
if (res < 0)
ret = res;
snd_soc_component_async_complete(cmpnt);
return ret;
}
static int asrc_config_sync(struct abox_data *data, int id, int stream,
unsigned int isr, unsigned int osr, unsigned int width,
int apf_coef)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
bool spus = (stream == SNDRV_PCM_STREAM_PLAYBACK);
const struct asrc_ctrl *ctrl;
unsigned int reg, mask, val;
int res, ret = 0;
abox_dbg(dev, "%s(%d, %d, %uHz, %uHz, %ubit, %d)\n", __func__,
id, stream, isr, osr, width, apf_coef);
ctrl = &asrc_table[to_asrc_rate(isr)][to_asrc_rate(osr)];
reg = spus ? ABOX_SPUS_ASRC_CTRL(id) : ABOX_SPUM_ASRC_CTRL(id);
mask = ABOX_ASRC_BIT_WIDTH_MASK;
val = ((width / 8) - 1) << ABOX_ASRC_BIT_WIDTH_L;
res = update_bits_async(dev, cmpnt, "width", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_IS_SYNC_MODE_MASK;
val = 0 << ABOX_ASRC_IS_SYNC_MODE_L;
res = update_bits_async(dev, cmpnt, "is sync", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OS_SYNC_MODE_MASK;
val = 0 << ABOX_ASRC_OS_SYNC_MODE_L;
res = update_bits_async(dev, cmpnt, "os sync", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OVSF_RATIO_MASK;
val = ctrl->ovsf << ABOX_ASRC_OVSF_RATIO_L;
res = update_bits_async(dev, cmpnt, "ovsf ratio", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_DCMF_RATIO_MASK;
val = ctrl->dcmf << ABOX_ASRC_DCMF_RATIO_L;
res = update_bits_async(dev, cmpnt, "dcmf ratio", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_IS_SOURCE_SEL_MASK;
val = TICK_SYNC << ABOX_ASRC_IS_SOURCE_SEL_L;
res = update_bits_async(dev, cmpnt, "is source", reg, mask, val);
if (res < 0)
ret = res;
mask = ABOX_ASRC_OS_SOURCE_SEL_MASK;
val = TICK_SYNC << ABOX_ASRC_OS_SOURCE_SEL_L;
res = update_bits_async(dev, cmpnt, "os source", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_IS_PARA0(id) : ABOX_SPUM_ASRC_IS_PARA0(id);
mask = ABOX_ASRC_IS_DEFAULT_MASK;
val = ctrl->ifactor;
res = update_bits_async(dev, cmpnt, "is default", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_IS_PARA1(id) : ABOX_SPUM_ASRC_IS_PARA1(id);
mask = ABOX_ASRC_IS_TPERIOD_LIMIT_MASK;
val = is_limit(val);
res = update_bits_async(dev, cmpnt, "is tperiod limit", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_OS_PARA0(id) : ABOX_SPUM_ASRC_OS_PARA0(id);
mask = ABOX_ASRC_OS_DEFAULT_MASK;
val = cal_ofactor(ctrl);
res = update_bits_async(dev, cmpnt, "os default", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_OS_PARA1(id) : ABOX_SPUM_ASRC_OS_PARA1(id);
mask = ABOX_ASRC_OS_TPERIOD_LIMIT_MASK;
val = os_limit(val);
res = update_bits_async(dev, cmpnt, "os tperiod limit", reg, mask, val);
if (res < 0)
ret = res;
reg = spus ? ABOX_SPUS_ASRC_FILTER_CTRL(id) :
ABOX_SPUM_ASRC_FILTER_CTRL(id);
mask = ABOX_ASRC_APF_COEF_SEL_MASK;
val = apf_coef << ABOX_ASRC_APF_COEF_SEL_L;
res = update_bits_async(dev, cmpnt, "apf coef sel", reg, mask, val);
if (res < 0)
ret = res;
snd_soc_component_async_complete(cmpnt);
return ret;
}
static int asrc_config(struct abox_data *data, int id, int stream,
enum asrc_tick itick, unsigned int isr,
enum asrc_tick otick, unsigned int osr,
unsigned int width, int apf_coef)
{
struct device *dev = data->dev;
int ret;
abox_info(dev, "%s(%d, %d, %d, %uHz, %d, %uHz, %ubit, %d)\n",
__func__, id, stream, itick, isr, otick, osr,
width, apf_coef);
if ((itick == TICK_SYNC) && (otick == TICK_SYNC)) {
ret = asrc_config_sync(data, id, stream, isr, osr, width,
apf_coef);
} else {
if (itick == TICK_CP) {
ret = asrc_config_async(data, id, stream,
itick, isr, otick, osr, s_default,
width, apf_coef);
} else if (otick == TICK_CP) {
ret = asrc_config_async(data, id, stream,
itick, isr, otick, osr, s_default,
width, apf_coef);
} else {
abox_err(dev, "not supported\n");
ret = -EINVAL;
}
}
return ret;
}
static int asrc_set(struct abox_data *data, int stream, int idx,
unsigned int channels, unsigned int rate, unsigned int tgt_rate,
unsigned int tgt_width)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
struct snd_soc_dapm_widget *w = asrc_get_widget(cmpnt, idx, stream);
enum asrc_tick itick, otick;
int apf_coef = get_apf_coef(data, stream, idx);
bool force_enable;
int on, ret;
abox_dbg(dev, "%s(%d, %d, %d, %uHz, %uHz, %ubit)\n", __func__,
stream, idx, channels, rate, tgt_rate, tgt_width);
ret = asrc_assign_id(w, stream, channels);
if (ret < 0)
abox_err(dev, "%s: assign failed: %d\n", __func__, ret);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
force_enable = spus_asrc_force_enable[idx];
itick = spus_asrc_is[idx];
otick = spus_asrc_os[idx];
ret = asrc_config(data, asrc_find_id(w, stream), stream,
itick, rate, otick, tgt_rate,
tgt_width, apf_coef);
} else {
force_enable = spum_asrc_force_enable[idx];
itick = spum_asrc_is[idx];
otick = spum_asrc_os[idx];
ret = asrc_config(data, asrc_find_id(w, stream), stream,
itick, tgt_rate, otick, rate,
tgt_width, apf_coef);
}
if (ret < 0)
abox_err(dev, "%s: config failed: %d\n", __func__, ret);
on = force_enable || (rate != tgt_rate) ||
(itick != TICK_SYNC) || (otick != TICK_SYNC);
ret = asrc_put_active(w, stream, on);
return ret;
}
static int asrc_event(struct snd_soc_dapm_widget *w, int e, int stream)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct device *dev = dapm->dev;
struct abox_data *data = dev_get_drvdata(dev);
int idx = asrc_get_idx(w);
struct device *dev_dma;
struct snd_soc_dai *dai_dma;
struct snd_pcm_hw_params params, tgt_params;
unsigned int tgt_rate = 0, tgt_width = 0;
unsigned int rate = 0, width = 0, channels = 0;
int id, ret = 0;
abox_dbg(dev, "%s(%s, %d)\n", __func__, w->name, e);
switch (e) {
case SND_SOC_DAPM_PRE_PMU:
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
dev_dma = data->dev_rdma[idx];
else
dev_dma = data->dev_wdma[idx];
ret = abox_dma_hw_params_fixup(dev_dma, NULL, &params);
if (ret < 0) {
abox_err(dev_dma, "hw params get failed: %d\n", ret);
break;
}
rate = params_rate(&params);
width = params_width(&params);
channels = params_channels(&params);
if (!rate || !width || !channels) {
abox_err(dev_dma, "hw params invalid: %u %u %u\n",
rate, width, channels);
ret = -EINVAL;
break;
}
dai_dma = abox_dma_get_dai(dev_dma, DMA_DAI_PCM);
if (IS_ERR_OR_NULL(dai_dma)) {
abox_err(dev_dma, "dai get failed: %ld\n",
PTR_ERR(dai_dma));
break;
}
tgt_params = params;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = rdma_hw_params_fixup(dai_dma, &tgt_params,
stream);
else
ret = wdma_hw_params_fixup(dai_dma, &tgt_params,
stream);
if (ret < 0)
abox_err(dev_dma, "hw params fixup failed: %d\n", ret);
tgt_rate = params_rate(&tgt_params);
tgt_width = params_width(&tgt_params);
ret = asrc_set(data, stream, idx, channels, rate, tgt_rate,
tgt_width);
if (ret < 0)
abox_err(dev, "%s: set failed: %d\n", __func__, ret);
break;
case SND_SOC_DAPM_POST_PMD:
/* ASRC will be released in DMA stop. */
break;
}
if (asrc_get_active(data->cmpnt, idx, stream)) {
id = asrc_get_id(data->cmpnt, idx, stream);
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
notify_event(data, ABOX_WIDGET_SPUS_ASRC0 + id, e);
else
notify_event(data, ABOX_WIDGET_SPUM_ASRC0 + id, e);
}
return ret;
}
static int spus_asrc_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
return asrc_event(w, e, SNDRV_PCM_STREAM_PLAYBACK);
}
static int spum_asrc_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int e)
{
return asrc_event(w, e, SNDRV_PCM_STREAM_CAPTURE);
}
static const char * const spus_inx_texts[] = {
"RDMA", "SIFSM", "RESERVED", "SIFST",
};
static SOC_ENUM_SINGLE_DECL(spus_in0_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_IN_L(0), spus_inx_texts);
static const struct snd_kcontrol_new spus_in0_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in0_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in1_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_IN_L(1), spus_inx_texts);
static const struct snd_kcontrol_new spus_in1_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in1_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in2_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_IN_L(2), spus_inx_texts);
static const struct snd_kcontrol_new spus_in2_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in2_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in3_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_IN_L(3), spus_inx_texts);
static const struct snd_kcontrol_new spus_in3_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in3_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in4_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_IN_L(4), spus_inx_texts);
static const struct snd_kcontrol_new spus_in4_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in4_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in5_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_IN_L(5), spus_inx_texts);
static const struct snd_kcontrol_new spus_in5_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in5_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in6_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_IN_L(6), spus_inx_texts);
static const struct snd_kcontrol_new spus_in6_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in6_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in7_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_IN_L(7), spus_inx_texts);
static const struct snd_kcontrol_new spus_in7_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in7_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in8_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_IN_L(8), spus_inx_texts);
static const struct snd_kcontrol_new spus_in8_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in8_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in9_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_IN_L(9), spus_inx_texts);
static const struct snd_kcontrol_new spus_in9_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in9_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in10_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_IN_L(10), spus_inx_texts);
static const struct snd_kcontrol_new spus_in10_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in10_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_in11_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_IN_L(11), spus_inx_texts);
static const struct snd_kcontrol_new spus_in11_controls[] = {
SOC_DAPM_ENUM("MUX", spus_in11_enum),
};
static const char * const spus_outx_texts[] = {
"RESERVED", "SIFS0", "SIFS1", "RESERVED", "SIFS2", "RESERVED",
"SIFS3", "RESERVED", "SIFS4", "SIDETONE-SIFS0", "SIFS5",
};
static SOC_ENUM_SINGLE_DECL(spus_out0_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_OUT_L(0), spus_outx_texts);
static const struct snd_kcontrol_new spus_out0_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out0_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out1_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_OUT_L(1), spus_outx_texts);
static const struct snd_kcontrol_new spus_out1_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out1_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out2_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_OUT_L(2), spus_outx_texts);
static const struct snd_kcontrol_new spus_out2_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out2_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out3_enum, ABOX_SPUS_CTRL_FC0,
ABOX_FUNC_CHAIN_SRC_OUT_L(3), spus_outx_texts);
static const struct snd_kcontrol_new spus_out3_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out3_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out4_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_OUT_L(4), spus_outx_texts);
static const struct snd_kcontrol_new spus_out4_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out4_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out5_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_OUT_L(5), spus_outx_texts);
static const struct snd_kcontrol_new spus_out5_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out5_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out6_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_OUT_L(6), spus_outx_texts);
static const struct snd_kcontrol_new spus_out6_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out6_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out7_enum, ABOX_SPUS_CTRL_FC1,
ABOX_FUNC_CHAIN_SRC_OUT_L(7), spus_outx_texts);
static const struct snd_kcontrol_new spus_out7_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out7_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out8_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_OUT_L(8), spus_outx_texts);
static const struct snd_kcontrol_new spus_out8_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out8_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out9_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_OUT_L(9), spus_outx_texts);
static const struct snd_kcontrol_new spus_out9_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out9_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out10_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_OUT_L(10), spus_outx_texts);
static const struct snd_kcontrol_new spus_out10_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out10_enum),
};
static SOC_ENUM_SINGLE_DECL(spus_out11_enum, ABOX_SPUS_CTRL_FC2,
ABOX_FUNC_CHAIN_SRC_OUT_L(11), spus_outx_texts);
static const struct snd_kcontrol_new spus_out11_controls[] = {
SOC_DAPM_ENUM("DEMUX", spus_out11_enum),
};
static const char * const spusm_texts[] = {
"RESERVED", "RESERVED", "RESERVED", "RESERVED",
"RESERVED", "RESERVED", "RESERVED", "RESERVED",
"UAIF0", "UAIF1", "UAIF2", "UAIF3",
"UAIF4", "UAIF5", "UAIF6", "RESERVED",
"BI_PDI0", "BI_PDI1", "BI_PDI2", "BI_PDI3",
"BI_PDI4", "BI_PDI5", "BI_PDI6", "BI_PDI7",
"RX_PDI0", "RX_PDI1", "RESERVED", "RESERVED",
"RESERVED", "RESERVED", "RESERVED", "SPDY",
};
static SOC_ENUM_SINGLE_DECL(spusm_enum, ABOX_ROUTE_CTRL0, ABOX_ROUTE_SPUSM_L,
spusm_texts);
static const struct snd_kcontrol_new spusm_controls[] = {
SOC_DAPM_ENUM("MUX", spusm_enum),
};
static SOC_ENUM_SINGLE_DECL(spust_enum, ABOX_ROUTE_CTRL2, ABOX_ROUTE_SPUST_L,
spusm_texts);
static const struct snd_kcontrol_new spust_controls[] = {
SOC_DAPM_ENUM("MUX", spust_enum),
};
int abox_cmpnt_sifsm_prepare(struct device *dev, struct abox_data *data,
enum abox_dai dai)
{
struct snd_soc_component *cmpnt = data->cmpnt;
enum abox_dai src;
unsigned int reg_val, val;
int idx, ret = 0;
abox_dbg(dev, "%s\n", __func__);
switch (get_source_dai_id(data, dai)) {
case ABOX_SIFSM:
/* ToDo */
break;
case ABOX_SIFST:
/* Needs force update. Flush is write only field. */
ret = regmap_update_bits_base(cmpnt->regmap, ABOX_SIDETONE_CTRL,
ABOX_SDTN_FLUSH_MASK, ABOX_SDTN_FLUSH_MASK,
NULL, false, true);
if (ret < 0)
break;
src = get_source_dai_id(data, ABOX_SIFST);
switch (src) {
case ABOX_UAIF0 ... ABOX_UAIF6:
idx = src - ABOX_UAIF0;
ret = snd_soc_component_read(cmpnt,
ABOX_UAIF_CTRL1(idx), &reg_val);
if (ret < 0)
break;
val = (reg_val & ABOX_FORMAT_MASK) >> ABOX_FORMAT_L;
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SIDETONE_CTRL,
ABOX_SDTN_FORMAT_MASK,
val << ABOX_SDTN_FORMAT_L);
break;
case ABOX_BI_PDI0 ... ABOX_BI_PDI3:
idx = src - ABOX_BI_PDI0;
ret = snd_soc_component_read(cmpnt, ABOX_SW_PDI_CTRL0,
&reg_val);
if (ret < 0)
break;
val = (reg_val & ABOX_BI_PDI_FORMAT_MASK(idx)) >>
ABOX_BI_PDI_FORMAT_L(idx);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SIDETONE_CTRL,
ABOX_SDTN_FORMAT_MASK,
val << ABOX_SDTN_FORMAT_L);
break;
case ABOX_BI_PDI4 ... ABOX_BI_PDI7:
idx = src - ABOX_BI_PDI4;
ret = snd_soc_component_read(cmpnt, ABOX_SW_PDI_CTRL1,
&reg_val);
if (ret < 0)
break;
val = (reg_val & ABOX_BI_PDI_FORMAT_MASK(idx)) >>
ABOX_BI_PDI_FORMAT_L(idx);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SIDETONE_CTRL,
ABOX_SDTN_FORMAT_MASK,
val << ABOX_SDTN_FORMAT_L);
break;
case ABOX_TX_PDI0 ... ABOX_TX_PDI2:
idx = src - ABOX_TX_PDI0;
ret = snd_soc_component_read(cmpnt, ABOX_SW_PDI_CTRL2,
&reg_val);
if (ret < 0)
break;
val = (reg_val & ABOX_TX_PDI_FORMAT_MASK(idx)) >>
ABOX_TX_PDI_FORMAT_L(idx);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SIDETONE_CTRL,
ABOX_SDTN_FORMAT_MASK,
val << ABOX_SDTN_FORMAT_L);
break;
case ABOX_RX_PDI0 ... ABOX_RX_PDI1:
idx = src - ABOX_RX_PDI0;
ret = snd_soc_component_read(cmpnt, ABOX_SW_PDI_CTRL3,
&reg_val);
if (ret < 0)
break;
val = (reg_val & ABOX_RX_PDI_FORMAT_MASK(idx)) >>
ABOX_RX_PDI_FORMAT_L(idx);
ret = snd_soc_component_update_bits(cmpnt,
ABOX_SIDETONE_CTRL,
ABOX_SDTN_FORMAT_MASK,
val << ABOX_SDTN_FORMAT_L);
break;
default:
ret = -EINVAL;
break;
}
break;
default:
/* nothing to do */
break;
}
return ret;
}
static const char * const sidetone_mode_texts[] = {
"Normal", "Zero", "Bypass",
};
static SOC_ENUM_SINGLE_DECL(sidetone_mode, ABOX_SIDETONE_CTRL,
ABOX_SDTN_ZERO_OUTPUT_L, sidetone_mode_texts);
static DECLARE_TLV_DB_LINEAR(sidetone_gain_tlv, 0, 3600);
static const char * const sidetone_headroom_hpf_texts[] = {
"6dB", "12dB", "18dB", "24dB",
};
static const unsigned int sidetone_headroom_hpf_values[] = {
2, 3, 4, 5,
};
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_hpf,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_HPF_L,
ABOX_SDTN_HEADROOM_HPF_MASK, sidetone_headroom_hpf_texts,
sidetone_headroom_hpf_values);
static const char * const sidetone_headroom_eq_texts[] = {
"12dB", "18dB", "24dB",
};
static const unsigned int sidetone_headroom_eq_values[] = {
3, 4, 5,
};
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_peak0,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_PEAK0_L,
ABOX_SDTN_HEADROOM_PEAK0_MASK, sidetone_headroom_eq_texts,
sidetone_headroom_eq_values);
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_peak1,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_PEAK1_L,
ABOX_SDTN_HEADROOM_PEAK0_MASK, sidetone_headroom_eq_texts,
sidetone_headroom_eq_values);
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_peak2,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_PEAK2_L,
ABOX_SDTN_HEADROOM_PEAK0_MASK, sidetone_headroom_eq_texts,
sidetone_headroom_eq_values);
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_lowsh,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_LOWSH_L,
ABOX_SDTN_HEADROOM_PEAK0_MASK, sidetone_headroom_eq_texts,
sidetone_headroom_eq_values);
static SOC_VALUE_ENUM_SINGLE_DECL(sidetone_headroom_highsh,
ABOX_SIDETONE_FILTER_CTRL0, ABOX_SDTN_HEADROOM_HIGHSH_L,
ABOX_SDTN_HEADROOM_PEAK0_MASK, sidetone_headroom_eq_texts,
sidetone_headroom_eq_values);
static struct snd_kcontrol_new sidetone_controls[] = {
SOC_SINGLE("SIDETONE IN CH", ABOX_SIDETONE_CTRL,
ABOX_SDTN_CH_SEL_IN_L, 1, 0),
SOC_SINGLE("SIDETONE OUT CH", ABOX_SIDETONE_CTRL,
ABOX_SDTN_CH_SEL_OUT_L, 1, 0),
SOC_SINGLE("SIDETONE OUT2 CH", ABOX_SIDETONE_CTRL,
ABOX_SDTN_CH_SEL_OUT2_L, 1, 0),
SOC_SINGLE("SIDETONE OUT2 EN", ABOX_SIDETONE_CTRL,
ABOX_SDTN_OUT2_ENABLE_L, 1, 0),
SOC_ENUM("SIDETONE MODE", sidetone_mode),
SOC_SINGLE("SIDETONE HPF EN", ABOX_SIDETONE_CTRL,
ABOX_SDTN_HPF_ENABLE_L, 1, 0),
SOC_SINGLE("SIDETONE EQ EN", ABOX_SIDETONE_CTRL,
ABOX_SDTN_EQ_ENABLE_L, 1, 0),
SOC_SINGLE("SIDETONE GAIN IN EN", ABOX_SIDETONE_CTRL,
ABOX_SDTN_GAIN_IN_ENABLE_L, 1, 0),
SOC_SINGLE("SIDETONE GAIN OUT EN", ABOX_SIDETONE_CTRL,
ABOX_SDTN_GAIN_OUT_ENABLE_L, 1, 0),
SOC_SINGLE_TLV("SIDETONE GAIN IN", ABOX_SIDETONE_GAIN_CTRL,
ABOX_SDTN_GAIN_IN_L, 133, 0, sidetone_gain_tlv),
SOC_SINGLE_TLV("SIDETONE GAIN OUT", ABOX_SIDETONE_GAIN_CTRL,
ABOX_SDTN_GAIN_OUT_L, 133, 0, sidetone_gain_tlv),
SOC_ENUM("SIDETONE HEADROOM HPF", sidetone_headroom_hpf),
SOC_ENUM("SIDETONE HEADROOM PEAK0", sidetone_headroom_peak0),
SOC_ENUM("SIDETONE HEADROOM PEAK1", sidetone_headroom_peak1),
SOC_ENUM("SIDETONE HEADROOM PEAK2", sidetone_headroom_peak2),
SOC_ENUM("SIDETONE HEADROOM LOWSH", sidetone_headroom_lowsh),
SOC_ENUM("SIDETONE HEADROOM HIGHSH", sidetone_headroom_highsh),
SOC_SINGLE("SIDETONE POSTAMP HPF", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_HPF_L, 3, 0),
SOC_SINGLE("SIDETONE POSTAMP PEAK0", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_PEAK0_L, 3, 0),
SOC_SINGLE("SIDETONE POSTAMP PEAK1", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_PEAK1_L, 3, 0),
SOC_SINGLE("SIDETONE POSTAMP PEAK2", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_PEAK2_L, 3, 0),
SOC_SINGLE("SIDETONE POSTAMP LOWSH", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_LOWSH_L, 3, 0),
SOC_SINGLE("SIDETONE POSTAMP HIGHSH", ABOX_SIDETONE_FILTER_CTRL1,
ABOX_SDTN_POSTAMP_HIGHSH_L, 3, 0),
SOC_SINGLE_XR_SX("SIDETONE HPF COEF0", ABOX_SIDETONE_HPF_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HPF COEF1", ABOX_SIDETONE_HPF_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HPF COEF2", ABOX_SIDETONE_HPF_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HPF COEF3", ABOX_SIDETONE_HPF_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HPF COEF4", ABOX_SIDETONE_HPF_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK0 COEF0", ABOX_SIDETONE_PEAK0_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK0 COEF1", ABOX_SIDETONE_PEAK0_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK0 COEF2", ABOX_SIDETONE_PEAK0_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK0 COEF3", ABOX_SIDETONE_PEAK0_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK0 COEF4", ABOX_SIDETONE_PEAK0_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK1 COEF0", ABOX_SIDETONE_PEAK1_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK1 COEF1", ABOX_SIDETONE_PEAK1_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK1 COEF2", ABOX_SIDETONE_PEAK1_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK1 COEF3", ABOX_SIDETONE_PEAK1_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK1 COEF4", ABOX_SIDETONE_PEAK1_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK2 COEF0", ABOX_SIDETONE_PEAK2_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK2 COEF1", ABOX_SIDETONE_PEAK2_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK2 COEF2", ABOX_SIDETONE_PEAK2_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK2 COEF3", ABOX_SIDETONE_PEAK2_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE PEAK2 COEF4", ABOX_SIDETONE_PEAK2_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE LOWSH COEF0", ABOX_SIDETONE_LOWSH_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE LOWSH COEF1", ABOX_SIDETONE_LOWSH_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE LOWSH COEF2", ABOX_SIDETONE_LOWSH_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE LOWSH COEF3", ABOX_SIDETONE_LOWSH_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE LOWSH COEF4", ABOX_SIDETONE_LOWSH_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HIGHSH COEF0", ABOX_SIDETONE_HIGHSH_COEF0,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HIGHSH COEF1", ABOX_SIDETONE_HIGHSH_COEF1,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HIGHSH COEF2", ABOX_SIDETONE_HIGHSH_COEF2,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HIGHSH COEF3", ABOX_SIDETONE_HIGHSH_COEF3,
1, 32, INT_MIN, INT_MAX, 0),
SOC_SINGLE_XR_SX("SIDETONE HIGHSH COEF4", ABOX_SIDETONE_HIGHSH_COEF4,
1, 32, INT_MIN, INT_MAX, 0),
};
static const struct snd_soc_dapm_route sidetone_routes[] = {
{"SIDETONE", NULL, "SPUST"},
{"SIFST", NULL, "SIDETONE"},
};
static const char * const sifsx_texts[] = {
"SPUS OUT0", "SPUS OUT1", "SPUS OUT2", "SPUS OUT3",
"SPUS OUT4", "SPUS OUT5", "SPUS OUT6", "SPUS OUT7",
"SPUS OUT8", "SPUS OUT9", "SPUS OUT10", "SPUS OUT11",
"RESERVED",
};
static SOC_ENUM_SINGLE_DECL(sifs1_enum, ABOX_SPUS_CTRL1, ABOX_SIFS_OUT_SEL_L(1),
sifsx_texts);
static const struct snd_kcontrol_new sifs1_controls[] = {
SOC_DAPM_ENUM("MUX", sifs1_enum),
};
static SOC_ENUM_SINGLE_DECL(sifs2_enum, ABOX_SPUS_CTRL1, ABOX_SIFS_OUT_SEL_L(2),
sifsx_texts);
static const struct snd_kcontrol_new sifs2_controls[] = {
SOC_DAPM_ENUM("MUX", sifs2_enum),
};
static SOC_ENUM_SINGLE_DECL(sifs3_enum, ABOX_SPUS_CTRL1, ABOX_SIFS_OUT_SEL_L(3),
sifsx_texts);
static const struct snd_kcontrol_new sifs3_controls[] = {
SOC_DAPM_ENUM("MUX", sifs3_enum),
};
static SOC_ENUM_SINGLE_DECL(sifs4_enum, ABOX_SPUS_CTRL1, ABOX_SIFS_OUT_SEL_L(4),
sifsx_texts);
static const struct snd_kcontrol_new sifs4_controls[] = {
SOC_DAPM_ENUM("MUX", sifs4_enum),
};
static SOC_ENUM_SINGLE_DECL(sifs5_enum, ABOX_SPUS_CTRL1, ABOX_SIFS_OUT_SEL_L(5),
sifsx_texts);
static const struct snd_kcontrol_new sifs5_controls[] = {
SOC_DAPM_ENUM("MUX", sifs5_enum),
};
static const struct snd_kcontrol_new sifs0_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new sifs1_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new sifs2_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new sifs3_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new sifs4_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new sifs5_out_controls[] = {
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const char * const sifsm_texts[] = {
"SPUS IN0", "SPUS IN1", "SPUS IN2", "SPUS IN3",
"SPUS IN4", "SPUS IN5", "SPUS IN6", "SPUS IN7",
"SPUS IN8", "SPUS IN9", "SPUS IN10", "SPUS IN11",
"RESERVED",
};
static SOC_ENUM_SINGLE_DECL(sifsm_enum, ABOX_SPUS_CTRL1, ABOX_SIFSM_IN_SEL_L,
sifsm_texts);
static const struct snd_kcontrol_new sifsm_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifsm_enum),
};
static SOC_ENUM_SINGLE_DECL(sifst_enum, ABOX_SPUS_CTRL2, ABOX_SIFST_IN_SEL_L,
sifsm_texts);
static const struct snd_kcontrol_new sifst_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifst_enum),
};
static const char * const uaif_spkx_texts[] = {
"RESERVED", "SIFS0", "SIFS1", "SIFS2",
"SIFS3", "SIFS4", "SIFS5", "RESERVED",
"RESERVED", "RESERVED", "RESERVED", "RESERVED",
"SIFMS",
};
static SOC_ENUM_SINGLE_DECL(uaif0_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(0), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif0_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif0_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif1_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(1), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif1_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif1_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif2_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(2), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif2_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif2_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif3_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(3), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif3_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif3_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif4_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(4), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif4_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif4_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif5_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(5), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif5_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif5_spk_enum),
};
static SOC_ENUM_SINGLE_DECL(uaif6_spk_enum, ABOX_ROUTE_CTRL0,
ABOX_ROUTE_UAIF_SPK_L(6), uaif_spkx_texts);
static const struct snd_kcontrol_new uaif6_spk_controls[] = {
SOC_DAPM_ENUM("MUX", uaif6_spk_enum),
};
static const char * const dsif_spk_texts[] = {
"RESERVED", "RESERVED", "SIFS1", "SIFS2", "SIFS3", "SIFS4", "SIFS5",
};
static SOC_ENUM_SINGLE_DECL(dsif_spk_enum, ABOX_ROUTE_CTRL0, ABOX_ROUTE_DSIF_L,
dsif_spk_texts);
static const struct snd_kcontrol_new dsif_spk_controls[] = {
SOC_DAPM_ENUM("MUX", dsif_spk_enum),
};
static const struct snd_kcontrol_new uaif0_controls[] = {
SOC_DAPM_SINGLE("UAIF0 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif1_controls[] = {
SOC_DAPM_SINGLE("UAIF1 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif2_controls[] = {
SOC_DAPM_SINGLE("UAIF2 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif3_controls[] = {
SOC_DAPM_SINGLE("UAIF3 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif4_controls[] = {
SOC_DAPM_SINGLE("UAIF4 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif5_controls[] = {
SOC_DAPM_SINGLE("UAIF5 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new uaif6_controls[] = {
SOC_DAPM_SINGLE("UAIF6 Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new dsif_controls[] = {
SOC_DAPM_SINGLE("DSIF Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const struct snd_kcontrol_new spdy_controls[] = {
SOC_DAPM_SINGLE("SPDY Switch", SND_SOC_NOPM, 0, 1, 1),
};
static const char * const rsrcx_texts[] = {
"RESERVED", "SIFS0", "SIFS1", "SIFS2",
"SIFS3", "SIFS4", "RESERVED", "RESERVED",
"UAIF0", "UAIF1", "UAIF2", "UAIF3",
};
static SOC_ENUM_SINGLE_DECL(rsrc0_enum, ABOX_ROUTE_CTRL2, ABOX_ROUTE_RSRC_L(0),
rsrcx_texts);
static const struct snd_kcontrol_new rsrc0_controls[] = {
SOC_DAPM_ENUM("DEMUX", rsrc0_enum),
};
static SOC_ENUM_SINGLE_DECL(rsrc1_enum, ABOX_ROUTE_CTRL2, ABOX_ROUTE_RSRC_L(1),
rsrcx_texts);
static const struct snd_kcontrol_new rsrc1_controls[] = {
SOC_DAPM_ENUM("DEMUX", rsrc1_enum),
};
static const char * const nsrcx_texts[] = {
"RESERVED", "SIFS0", "SIFS1", "SIFS2",
"SIFS3", "SIFS4", "SIFS5", "RESERVED",
"UAIF0", "UAIF1", "UAIF2", "UAIF3",
"UAIF4", "UAIF5", "UAIF6", "RESERVED",
"BI_PDI0", "BI_PDI1", "BI_PDI2", "BI_PDI3",
"BI_PDI4", "BI_PDI5", "BI_PDI6", "BI_PDI7",
"RX_PDI0", "RX_PDI1", "RESERVED", "RESERVED",
"RESERVED", "RESERVED", "RESERVED", "SPDY",
};
static SOC_ENUM_SINGLE_DECL(nsrc0_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(0),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc0_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc0_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc1_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(1),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc1_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc1_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc2_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(2),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc2_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc2_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc3_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(3),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc3_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc3_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc4_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(4),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc4_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc4_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc5_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(5),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc5_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc5_enum),
};
static SOC_ENUM_SINGLE_DECL(nsrc6_enum, ABOX_ROUTE_CTRL1, ABOX_ROUTE_NSRC_L(6),
nsrcx_texts);
static const struct snd_kcontrol_new nsrc6_controls[] = {
SOC_DAPM_ENUM("DEMUX", nsrc6_enum),
};
static const struct snd_kcontrol_new recp_controls[] = {
SOC_DAPM_SINGLE("PIFS0", ABOX_SPUM_CTRL1, ABOX_RECP_SRC_VALID_L, 1, 0),
SOC_DAPM_SINGLE("PIFS1", ABOX_SPUM_CTRL1, ABOX_RECP_SRC_VALID_H, 1, 0),
};
static const char * const sifmx_texts[] = {
"WDMA", "SIFMS",
};
static SOC_ENUM_SINGLE_DECL(sifm0_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(0), sifmx_texts);
static const struct snd_kcontrol_new sifm0_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm0_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm1_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(1), sifmx_texts);
static const struct snd_kcontrol_new sifm1_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm1_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm2_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(2), sifmx_texts);
static const struct snd_kcontrol_new sifm2_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm2_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm3_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(3), sifmx_texts);
static const struct snd_kcontrol_new sifm3_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm3_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm4_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(4), sifmx_texts);
static const struct snd_kcontrol_new sifm4_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm4_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm5_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(5), sifmx_texts);
static const struct snd_kcontrol_new sifm5_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm5_enum),
};
static SOC_ENUM_SINGLE_DECL(sifm6_enum, ABOX_SPUM_CTRL0,
ABOX_FUNC_CHAIN_NSRC_OUT_L(6), sifmx_texts);
static const struct snd_kcontrol_new sifm6_controls[] = {
SOC_DAPM_ENUM("DEMUX", sifm6_enum),
};
static const char * const sifms_texts[] = {
"RESERVED", "SIFM0", "SIFM1", "SIFM2",
"SIFM3", "SIFM4", "SIFM5", "SIFM6",
};
static SOC_ENUM_SINGLE_DECL(sifms_enum, ABOX_SPUM_CTRL1, ABOX_SIFMS_OUT_SEL_L,
sifms_texts);
static const struct snd_kcontrol_new sifms_controls[] = {
SOC_DAPM_ENUM("MUX", sifms_enum),
};
static const struct snd_soc_dapm_widget cmpnt_widgets[] = {
SND_SOC_DAPM_MUX("SPUSM", SND_SOC_NOPM, 0, 0, spusm_controls),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN6", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN7", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN8", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN9", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN10", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFSM-SPUS IN11", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_DEMUX("SIFSM", SND_SOC_NOPM, 0, 0, sifsm_controls),
SND_SOC_DAPM_MUX("SPUST", SND_SOC_NOPM, 0, 0, spust_controls),
SND_SOC_DAPM_PGA("SIDETONE", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN6", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN7", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN8", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN9", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN10", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFST-SPUS IN11", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_DEMUX("SIFST", SND_SOC_NOPM, 0, 0, sifst_controls),
SND_SOC_DAPM_MUX_E("SPUS IN0", SND_SOC_NOPM, 0, 0, spus_in0_controls,
spus_in0_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN1", SND_SOC_NOPM, 0, 0, spus_in1_controls,
spus_in1_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN2", SND_SOC_NOPM, 0, 0, spus_in2_controls,
spus_in2_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN3", SND_SOC_NOPM, 0, 0, spus_in3_controls,
spus_in3_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN4", SND_SOC_NOPM, 0, 0, spus_in4_controls,
spus_in4_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN5", SND_SOC_NOPM, 0, 0, spus_in5_controls,
spus_in5_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN6", SND_SOC_NOPM, 0, 0, spus_in6_controls,
spus_in6_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN7", SND_SOC_NOPM, 0, 0, spus_in7_controls,
spus_in7_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN8", SND_SOC_NOPM, 0, 0, spus_in8_controls,
spus_in8_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN9", SND_SOC_NOPM, 0, 0, spus_in9_controls,
spus_in9_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN10", SND_SOC_NOPM, 0, 0, spus_in10_controls,
spus_in10_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SPUS IN11", SND_SOC_NOPM, 0, 0, spus_in11_controls,
spus_in11_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC0", SND_SOC_NOPM, 0, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC1", SND_SOC_NOPM, 1, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC2", SND_SOC_NOPM, 2, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC3", SND_SOC_NOPM, 3, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC4", SND_SOC_NOPM, 4, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC5", SND_SOC_NOPM, 5, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC6", SND_SOC_NOPM, 6, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC7", SND_SOC_NOPM, 7, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC8", SND_SOC_NOPM, 8, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC9", SND_SOC_NOPM, 9, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC10", SND_SOC_NOPM, 10, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUS ASRC11", SND_SOC_NOPM, 11, 0, NULL, 0,
spus_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DEMUX("SPUS OUT0", SND_SOC_NOPM, 0, 0, spus_out0_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT1", SND_SOC_NOPM, 0, 0, spus_out1_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT2", SND_SOC_NOPM, 0, 0, spus_out2_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT3", SND_SOC_NOPM, 0, 0, spus_out3_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT4", SND_SOC_NOPM, 0, 0, spus_out4_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT5", SND_SOC_NOPM, 0, 0, spus_out5_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT6", SND_SOC_NOPM, 0, 0, spus_out6_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT7", SND_SOC_NOPM, 0, 0, spus_out7_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT8", SND_SOC_NOPM, 0, 0, spus_out8_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT9", SND_SOC_NOPM, 0, 0, spus_out9_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT10", SND_SOC_NOPM, 0, 0,
spus_out10_controls),
SND_SOC_DAPM_DEMUX("SPUS OUT11", SND_SOC_NOPM, 0, 0,
spus_out11_controls),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT0-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT1-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT2-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT3-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT4-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT5-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT6-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT7-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT8-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT9-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT10-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SPUS OUT11-SIFS5", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER_E("SIFS0", SND_SOC_NOPM, 0, 0, NULL, 0,
sifs0_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SIFS1", SND_SOC_NOPM, 0, 0, sifs1_controls,
sifs1_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SIFS2", SND_SOC_NOPM, 0, 0, sifs2_controls,
sifs2_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SIFS3", SND_SOC_NOPM, 0, 0, sifs3_controls,
sifs3_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SIFS4", SND_SOC_NOPM, 0, 0, sifs4_controls,
sifs4_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("SIFS5", SND_SOC_NOPM, 0, 0, sifs5_controls,
sifs5_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SWITCH("SIFS0 OUT", SND_SOC_NOPM, 0, 0,
sifs0_out_controls),
SND_SOC_DAPM_SWITCH("SIFS1 OUT", SND_SOC_NOPM, 0, 0,
sifs1_out_controls),
SND_SOC_DAPM_SWITCH("SIFS2 OUT", SND_SOC_NOPM, 0, 0,
sifs2_out_controls),
SND_SOC_DAPM_SWITCH("SIFS3 OUT", SND_SOC_NOPM, 0, 0,
sifs3_out_controls),
SND_SOC_DAPM_SWITCH("SIFS4 OUT", SND_SOC_NOPM, 0, 0,
sifs4_out_controls),
SND_SOC_DAPM_SWITCH("SIFS5 OUT", SND_SOC_NOPM, 0, 0,
sifs5_out_controls),
SND_SOC_DAPM_MUX("UAIF0 SPK", SND_SOC_NOPM, 0, 0, uaif0_spk_controls),
SND_SOC_DAPM_MUX("UAIF1 SPK", SND_SOC_NOPM, 0, 0, uaif1_spk_controls),
SND_SOC_DAPM_MUX("UAIF2 SPK", SND_SOC_NOPM, 0, 0, uaif2_spk_controls),
SND_SOC_DAPM_MUX("UAIF3 SPK", SND_SOC_NOPM, 0, 0, uaif3_spk_controls),
SND_SOC_DAPM_MUX("UAIF4 SPK", SND_SOC_NOPM, 0, 0, uaif4_spk_controls),
SND_SOC_DAPM_MUX("UAIF5 SPK", SND_SOC_NOPM, 0, 0, uaif5_spk_controls),
SND_SOC_DAPM_MUX("UAIF6 SPK", SND_SOC_NOPM, 0, 0, uaif6_spk_controls),
SND_SOC_DAPM_MUX("DSIF SPK", SND_SOC_NOPM, 0, 0, dsif_spk_controls),
SND_SOC_DAPM_SWITCH("UAIF0 PLA", SND_SOC_NOPM, 0, 0, uaif0_controls),
SND_SOC_DAPM_SWITCH("UAIF1 PLA", SND_SOC_NOPM, 0, 0, uaif1_controls),
SND_SOC_DAPM_SWITCH("UAIF2 PLA", SND_SOC_NOPM, 0, 0, uaif2_controls),
SND_SOC_DAPM_SWITCH("UAIF3 PLA", SND_SOC_NOPM, 0, 0, uaif3_controls),
SND_SOC_DAPM_SWITCH("UAIF4 PLA", SND_SOC_NOPM, 0, 0, uaif4_controls),
SND_SOC_DAPM_SWITCH("UAIF5 PLA", SND_SOC_NOPM, 0, 0, uaif5_controls),
SND_SOC_DAPM_SWITCH("UAIF6 PLA", SND_SOC_NOPM, 0, 0, uaif6_controls),
SND_SOC_DAPM_SWITCH("DSIF PLA", SND_SOC_NOPM, 0, 0, dsif_controls),
SND_SOC_DAPM_SWITCH("UAIF0 CAP", SND_SOC_NOPM, 0, 0, uaif0_controls),
SND_SOC_DAPM_SWITCH("UAIF1 CAP", SND_SOC_NOPM, 0, 0, uaif1_controls),
SND_SOC_DAPM_SWITCH("UAIF2 CAP", SND_SOC_NOPM, 0, 0, uaif2_controls),
SND_SOC_DAPM_SWITCH("UAIF3 CAP", SND_SOC_NOPM, 0, 0, uaif3_controls),
SND_SOC_DAPM_SWITCH("UAIF4 CAP", SND_SOC_NOPM, 0, 0, uaif4_controls),
SND_SOC_DAPM_SWITCH("UAIF5 CAP", SND_SOC_NOPM, 0, 0, uaif5_controls),
SND_SOC_DAPM_SWITCH("UAIF6 CAP", SND_SOC_NOPM, 0, 0, uaif6_controls),
SND_SOC_DAPM_SWITCH("SPDY CAP", SND_SOC_NOPM, 0, 0, spdy_controls),
SND_SOC_DAPM_MUX_E("NSRC0", SND_SOC_NOPM, 0, 0, nsrc0_controls,
nsrc0_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("NSRC1", SND_SOC_NOPM, 0, 0, nsrc1_controls,
nsrc1_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("NSRC2", SND_SOC_NOPM, 0, 0, nsrc2_controls,
nsrc2_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("NSRC3", SND_SOC_NOPM, 0, 0, nsrc3_controls,
nsrc3_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("NSRC4", SND_SOC_NOPM, 0, 0, nsrc4_controls,
nsrc4_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUM ASRC0", SND_SOC_NOPM, 0, 0, NULL, 0,
spum_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUM ASRC1", SND_SOC_NOPM, 1, 0, NULL, 0,
spum_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUM ASRC2", SND_SOC_NOPM, 2, 0, NULL, 0,
spum_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUM ASRC3", SND_SOC_NOPM, 3, 0, NULL, 0,
spum_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("SPUM ASRC4", SND_SOC_NOPM, 4, 0, NULL, 0,
spum_asrc_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DEMUX("SIFM0", SND_SOC_NOPM, 0, 0, sifm0_controls),
SND_SOC_DAPM_DEMUX("SIFM1", SND_SOC_NOPM, 0, 0, sifm1_controls),
SND_SOC_DAPM_DEMUX("SIFM2", SND_SOC_NOPM, 0, 0, sifm2_controls),
SND_SOC_DAPM_DEMUX("SIFM3", SND_SOC_NOPM, 0, 0, sifm3_controls),
SND_SOC_DAPM_DEMUX("SIFM4", SND_SOC_NOPM, 0, 0, sifm4_controls),
SND_SOC_DAPM_PGA("SIFM0-SIFMS", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFM1-SIFMS", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFM2-SIFMS", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFM3-SIFMS", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("SIFM4-SIFMS", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("SIFMS", SND_SOC_NOPM, 0, 0, sifms_controls),
};
static const struct snd_soc_dapm_route cmpnt_routes[] = {
/* sink, control, source */
{"SIFSM", NULL, "SPUSM"},
{"SIFSM-SPUS IN0", "SPUS IN0", "SIFSM"},
{"SIFSM-SPUS IN1", "SPUS IN1", "SIFSM"},
{"SIFSM-SPUS IN2", "SPUS IN2", "SIFSM"},
{"SIFSM-SPUS IN3", "SPUS IN3", "SIFSM"},
{"SIFSM-SPUS IN4", "SPUS IN4", "SIFSM"},
{"SIFSM-SPUS IN5", "SPUS IN5", "SIFSM"},
{"SIFSM-SPUS IN6", "SPUS IN6", "SIFSM"},
{"SIFSM-SPUS IN7", "SPUS IN7", "SIFSM"},
{"SIFSM-SPUS IN8", "SPUS IN8", "SIFSM"},
{"SIFSM-SPUS IN9", "SPUS IN9", "SIFSM"},
{"SIFSM-SPUS IN10", "SPUS IN10", "SIFSM"},
{"SIFSM-SPUS IN11", "SPUS IN11", "SIFSM"},
{"SPUS IN0", "SIFSM", "SIFSM-SPUS IN0"},
{"SPUS IN1", "SIFSM", "SIFSM-SPUS IN1"},
{"SPUS IN2", "SIFSM", "SIFSM-SPUS IN2"},
{"SPUS IN3", "SIFSM", "SIFSM-SPUS IN3"},
{"SPUS IN4", "SIFSM", "SIFSM-SPUS IN4"},
{"SPUS IN5", "SIFSM", "SIFSM-SPUS IN5"},
{"SPUS IN6", "SIFSM", "SIFSM-SPUS IN6"},
{"SPUS IN7", "SIFSM", "SIFSM-SPUS IN7"},
{"SPUS IN8", "SIFSM", "SIFSM-SPUS IN8"},
{"SPUS IN9", "SIFSM", "SIFSM-SPUS IN9"},
{"SPUS IN10", "SIFSM", "SIFSM-SPUS IN10"},
{"SPUS IN11", "SIFSM", "SIFSM-SPUS IN11"},
{"SIFST-SPUS IN0", "SPUS IN0", "SIFST"},
{"SIFST-SPUS IN1", "SPUS IN1", "SIFST"},
{"SIFST-SPUS IN2", "SPUS IN2", "SIFST"},
{"SIFST-SPUS IN3", "SPUS IN3", "SIFST"},
{"SIFST-SPUS IN4", "SPUS IN4", "SIFST"},
{"SIFST-SPUS IN5", "SPUS IN5", "SIFST"},
{"SIFST-SPUS IN6", "SPUS IN6", "SIFST"},
{"SIFST-SPUS IN7", "SPUS IN7", "SIFST"},
{"SIFST-SPUS IN8", "SPUS IN8", "SIFST"},
{"SIFST-SPUS IN9", "SPUS IN9", "SIFST"},
{"SIFST-SPUS IN10", "SPUS IN10", "SIFST"},
{"SIFST-SPUS IN11", "SPUS IN11", "SIFST"},
{"SPUS IN0", "SIFST", "SIFST-SPUS IN0"},
{"SPUS IN1", "SIFST", "SIFST-SPUS IN1"},
{"SPUS IN2", "SIFST", "SIFST-SPUS IN2"},
{"SPUS IN3", "SIFST", "SIFST-SPUS IN3"},
{"SPUS IN4", "SIFST", "SIFST-SPUS IN4"},
{"SPUS IN5", "SIFST", "SIFST-SPUS IN5"},
{"SPUS IN6", "SIFST", "SIFST-SPUS IN6"},
{"SPUS IN7", "SIFST", "SIFST-SPUS IN7"},
{"SPUS IN8", "SIFST", "SIFST-SPUS IN8"},
{"SPUS IN9", "SIFST", "SIFST-SPUS IN9"},
{"SPUS IN10", "SIFST", "SIFST-SPUS IN10"},
{"SPUS IN11", "SIFST", "SIFST-SPUS IN11"},
{"SPUS ASRC0", NULL, "SPUS IN0"},
{"SPUS ASRC1", NULL, "SPUS IN1"},
{"SPUS ASRC2", NULL, "SPUS IN2"},
{"SPUS ASRC3", NULL, "SPUS IN3"},
{"SPUS ASRC4", NULL, "SPUS IN4"},
{"SPUS ASRC5", NULL, "SPUS IN5"},
{"SPUS ASRC6", NULL, "SPUS IN6"},
{"SPUS ASRC7", NULL, "SPUS IN7"},
{"SPUS ASRC8", NULL, "SPUS IN8"},
{"SPUS ASRC9", NULL, "SPUS IN9"},
{"SPUS ASRC10", NULL, "SPUS IN10"},
{"SPUS ASRC11", NULL, "SPUS IN11"},
{"SPUS OUT0", NULL, "SPUS ASRC0"},
{"SPUS OUT1", NULL, "SPUS ASRC1"},
{"SPUS OUT2", NULL, "SPUS ASRC2"},
{"SPUS OUT3", NULL, "SPUS ASRC3"},
{"SPUS OUT4", NULL, "SPUS ASRC4"},
{"SPUS OUT5", NULL, "SPUS ASRC5"},
{"SPUS OUT6", NULL, "SPUS ASRC6"},
{"SPUS OUT7", NULL, "SPUS ASRC7"},
{"SPUS OUT8", NULL, "SPUS ASRC8"},
{"SPUS OUT9", NULL, "SPUS ASRC9"},
{"SPUS OUT10", NULL, "SPUS ASRC10"},
{"SPUS OUT11", NULL, "SPUS ASRC11"},
{"SPUS OUT0-SIFS0", "SIFS0", "SPUS OUT0"},
{"SPUS OUT1-SIFS0", "SIFS0", "SPUS OUT1"},
{"SPUS OUT2-SIFS0", "SIFS0", "SPUS OUT2"},
{"SPUS OUT3-SIFS0", "SIFS0", "SPUS OUT3"},
{"SPUS OUT4-SIFS0", "SIFS0", "SPUS OUT4"},
{"SPUS OUT5-SIFS0", "SIFS0", "SPUS OUT5"},
{"SPUS OUT6-SIFS0", "SIFS0", "SPUS OUT6"},
{"SPUS OUT7-SIFS0", "SIFS0", "SPUS OUT7"},
{"SPUS OUT8-SIFS0", "SIFS0", "SPUS OUT8"},
{"SPUS OUT9-SIFS0", "SIFS0", "SPUS OUT9"},
{"SPUS OUT10-SIFS0", "SIFS0", "SPUS OUT10"},
{"SPUS OUT11-SIFS0", "SIFS0", "SPUS OUT11"},
{"SPUS OUT0-SIFS1", "SIFS1", "SPUS OUT0"},
{"SPUS OUT1-SIFS1", "SIFS1", "SPUS OUT1"},
{"SPUS OUT2-SIFS1", "SIFS1", "SPUS OUT2"},
{"SPUS OUT3-SIFS1", "SIFS1", "SPUS OUT3"},
{"SPUS OUT4-SIFS1", "SIFS1", "SPUS OUT4"},
{"SPUS OUT5-SIFS1", "SIFS1", "SPUS OUT5"},
{"SPUS OUT6-SIFS1", "SIFS1", "SPUS OUT6"},
{"SPUS OUT7-SIFS1", "SIFS1", "SPUS OUT7"},
{"SPUS OUT8-SIFS1", "SIFS1", "SPUS OUT8"},
{"SPUS OUT9-SIFS1", "SIFS1", "SPUS OUT9"},
{"SPUS OUT10-SIFS1", "SIFS1", "SPUS OUT10"},
{"SPUS OUT11-SIFS1", "SIFS1", "SPUS OUT11"},
{"SPUS OUT0-SIFS2", "SIFS2", "SPUS OUT0"},
{"SPUS OUT1-SIFS2", "SIFS2", "SPUS OUT1"},
{"SPUS OUT2-SIFS2", "SIFS2", "SPUS OUT2"},
{"SPUS OUT3-SIFS2", "SIFS2", "SPUS OUT3"},
{"SPUS OUT4-SIFS2", "SIFS2", "SPUS OUT4"},
{"SPUS OUT5-SIFS2", "SIFS2", "SPUS OUT5"},
{"SPUS OUT6-SIFS2", "SIFS2", "SPUS OUT6"},
{"SPUS OUT7-SIFS2", "SIFS2", "SPUS OUT7"},
{"SPUS OUT8-SIFS2", "SIFS2", "SPUS OUT8"},
{"SPUS OUT9-SIFS2", "SIFS2", "SPUS OUT9"},
{"SPUS OUT10-SIFS2", "SIFS2", "SPUS OUT10"},
{"SPUS OUT11-SIFS2", "SIFS2", "SPUS OUT11"},
{"SPUS OUT0-SIFS3", "SIFS3", "SPUS OUT0"},
{"SPUS OUT1-SIFS3", "SIFS3", "SPUS OUT1"},
{"SPUS OUT2-SIFS3", "SIFS3", "SPUS OUT2"},
{"SPUS OUT3-SIFS3", "SIFS3", "SPUS OUT3"},
{"SPUS OUT4-SIFS3", "SIFS3", "SPUS OUT4"},
{"SPUS OUT5-SIFS3", "SIFS3", "SPUS OUT5"},
{"SPUS OUT6-SIFS3", "SIFS3", "SPUS OUT6"},
{"SPUS OUT7-SIFS3", "SIFS3", "SPUS OUT7"},
{"SPUS OUT8-SIFS3", "SIFS3", "SPUS OUT8"},
{"SPUS OUT9-SIFS3", "SIFS3", "SPUS OUT9"},
{"SPUS OUT10-SIFS3", "SIFS3", "SPUS OUT10"},
{"SPUS OUT11-SIFS3", "SIFS3", "SPUS OUT11"},
{"SPUS OUT0-SIFS4", "SIFS4", "SPUS OUT0"},
{"SPUS OUT1-SIFS4", "SIFS4", "SPUS OUT1"},
{"SPUS OUT2-SIFS4", "SIFS4", "SPUS OUT2"},
{"SPUS OUT3-SIFS4", "SIFS4", "SPUS OUT3"},
{"SPUS OUT4-SIFS4", "SIFS4", "SPUS OUT4"},
{"SPUS OUT5-SIFS4", "SIFS4", "SPUS OUT5"},
{"SPUS OUT6-SIFS4", "SIFS4", "SPUS OUT6"},
{"SPUS OUT7-SIFS4", "SIFS4", "SPUS OUT7"},
{"SPUS OUT8-SIFS4", "SIFS4", "SPUS OUT8"},
{"SPUS OUT9-SIFS4", "SIFS4", "SPUS OUT9"},
{"SPUS OUT10-SIFS4", "SIFS4", "SPUS OUT10"},
{"SPUS OUT11-SIFS4", "SIFS4", "SPUS OUT11"},
{"SPUS OUT0-SIFS5", "SIFS5", "SPUS OUT0"},
{"SPUS OUT1-SIFS5", "SIFS5", "SPUS OUT1"},
{"SPUS OUT2-SIFS5", "SIFS5", "SPUS OUT2"},
{"SPUS OUT3-SIFS5", "SIFS5", "SPUS OUT3"},
{"SPUS OUT4-SIFS5", "SIFS5", "SPUS OUT4"},
{"SPUS OUT5-SIFS5", "SIFS5", "SPUS OUT5"},
{"SPUS OUT6-SIFS5", "SIFS5", "SPUS OUT6"},
{"SPUS OUT7-SIFS5", "SIFS5", "SPUS OUT7"},
{"SPUS OUT8-SIFS5", "SIFS5", "SPUS OUT8"},
{"SPUS OUT9-SIFS5", "SIFS5", "SPUS OUT9"},
{"SPUS OUT10-SIFS5", "SIFS5", "SPUS OUT10"},
{"SPUS OUT11-SIFS5", "SIFS5", "SPUS OUT11"},
{"SPUS OUT0-SIFS0", "SIDETONE-SIFS0", "SPUS OUT0"},
{"SPUS OUT1-SIFS0", "SIDETONE-SIFS0", "SPUS OUT1"},
{"SPUS OUT2-SIFS0", "SIDETONE-SIFS0", "SPUS OUT2"},
{"SPUS OUT3-SIFS0", "SIDETONE-SIFS0", "SPUS OUT3"},
{"SPUS OUT4-SIFS0", "SIDETONE-SIFS0", "SPUS OUT4"},
{"SPUS OUT5-SIFS0", "SIDETONE-SIFS0", "SPUS OUT5"},
{"SPUS OUT6-SIFS0", "SIDETONE-SIFS0", "SPUS OUT6"},
{"SPUS OUT7-SIFS0", "SIDETONE-SIFS0", "SPUS OUT7"},
{"SPUS OUT8-SIFS0", "SIDETONE-SIFS0", "SPUS OUT8"},
{"SPUS OUT9-SIFS0", "SIDETONE-SIFS0", "SPUS OUT9"},
{"SPUS OUT10-SIFS0", "SIDETONE-SIFS0", "SPUS OUT10"},
{"SPUS OUT11-SIFS0", "SIDETONE-SIFS0", "SPUS OUT11"},
{"SIFS0", NULL, "SPUS OUT0-SIFS0"},
{"SIFS0", NULL, "SPUS OUT1-SIFS0"},
{"SIFS0", NULL, "SPUS OUT2-SIFS0"},
{"SIFS0", NULL, "SPUS OUT3-SIFS0"},
{"SIFS0", NULL, "SPUS OUT4-SIFS0"},
{"SIFS0", NULL, "SPUS OUT5-SIFS0"},
{"SIFS0", NULL, "SPUS OUT6-SIFS0"},
{"SIFS0", NULL, "SPUS OUT7-SIFS0"},
{"SIFS0", NULL, "SPUS OUT8-SIFS0"},
{"SIFS0", NULL, "SPUS OUT9-SIFS0"},
{"SIFS0", NULL, "SPUS OUT10-SIFS0"},
{"SIFS0", NULL, "SPUS OUT11-SIFS0"},
{"SIFS1", "SPUS OUT0", "SPUS OUT0-SIFS1"},
{"SIFS1", "SPUS OUT1", "SPUS OUT1-SIFS1"},
{"SIFS1", "SPUS OUT2", "SPUS OUT2-SIFS1"},
{"SIFS1", "SPUS OUT3", "SPUS OUT3-SIFS1"},
{"SIFS1", "SPUS OUT4", "SPUS OUT4-SIFS1"},
{"SIFS1", "SPUS OUT5", "SPUS OUT5-SIFS1"},
{"SIFS1", "SPUS OUT6", "SPUS OUT6-SIFS1"},
{"SIFS1", "SPUS OUT7", "SPUS OUT7-SIFS1"},
{"SIFS1", "SPUS OUT8", "SPUS OUT8-SIFS1"},
{"SIFS1", "SPUS OUT9", "SPUS OUT9-SIFS1"},
{"SIFS1", "SPUS OUT10", "SPUS OUT10-SIFS1"},
{"SIFS1", "SPUS OUT11", "SPUS OUT11-SIFS1"},
{"SIFS2", "SPUS OUT0", "SPUS OUT0-SIFS2"},
{"SIFS2", "SPUS OUT1", "SPUS OUT1-SIFS2"},
{"SIFS2", "SPUS OUT2", "SPUS OUT2-SIFS2"},
{"SIFS2", "SPUS OUT3", "SPUS OUT3-SIFS2"},
{"SIFS2", "SPUS OUT4", "SPUS OUT4-SIFS2"},
{"SIFS2", "SPUS OUT5", "SPUS OUT5-SIFS2"},
{"SIFS2", "SPUS OUT6", "SPUS OUT6-SIFS2"},
{"SIFS2", "SPUS OUT7", "SPUS OUT7-SIFS2"},
{"SIFS2", "SPUS OUT8", "SPUS OUT8-SIFS2"},
{"SIFS2", "SPUS OUT9", "SPUS OUT9-SIFS2"},
{"SIFS2", "SPUS OUT10", "SPUS OUT10-SIFS2"},
{"SIFS2", "SPUS OUT11", "SPUS OUT11-SIFS2"},
{"SIFS3", "SPUS OUT0", "SPUS OUT0-SIFS3"},
{"SIFS3", "SPUS OUT1", "SPUS OUT1-SIFS3"},
{"SIFS3", "SPUS OUT2", "SPUS OUT2-SIFS3"},
{"SIFS3", "SPUS OUT3", "SPUS OUT3-SIFS3"},
{"SIFS3", "SPUS OUT4", "SPUS OUT4-SIFS3"},
{"SIFS3", "SPUS OUT5", "SPUS OUT5-SIFS3"},
{"SIFS3", "SPUS OUT6", "SPUS OUT6-SIFS3"},
{"SIFS3", "SPUS OUT7", "SPUS OUT7-SIFS3"},
{"SIFS3", "SPUS OUT8", "SPUS OUT8-SIFS3"},
{"SIFS3", "SPUS OUT9", "SPUS OUT9-SIFS3"},
{"SIFS3", "SPUS OUT10", "SPUS OUT10-SIFS3"},
{"SIFS3", "SPUS OUT11", "SPUS OUT11-SIFS3"},
{"SIFS4", "SPUS OUT0", "SPUS OUT0-SIFS4"},
{"SIFS4", "SPUS OUT1", "SPUS OUT1-SIFS4"},
{"SIFS4", "SPUS OUT2", "SPUS OUT2-SIFS4"},
{"SIFS4", "SPUS OUT3", "SPUS OUT3-SIFS4"},
{"SIFS4", "SPUS OUT4", "SPUS OUT4-SIFS4"},
{"SIFS4", "SPUS OUT5", "SPUS OUT5-SIFS4"},
{"SIFS4", "SPUS OUT6", "SPUS OUT6-SIFS4"},
{"SIFS4", "SPUS OUT7", "SPUS OUT7-SIFS4"},
{"SIFS4", "SPUS OUT8", "SPUS OUT8-SIFS4"},
{"SIFS4", "SPUS OUT9", "SPUS OUT9-SIFS4"},
{"SIFS4", "SPUS OUT10", "SPUS OUT10-SIFS4"},
{"SIFS4", "SPUS OUT11", "SPUS OUT11-SIFS4"},
{"SIFS5", "SPUS OUT0", "SPUS OUT0-SIFS5"},
{"SIFS5", "SPUS OUT1", "SPUS OUT1-SIFS5"},
{"SIFS5", "SPUS OUT2", "SPUS OUT2-SIFS5"},
{"SIFS5", "SPUS OUT3", "SPUS OUT3-SIFS5"},
{"SIFS5", "SPUS OUT4", "SPUS OUT4-SIFS5"},
{"SIFS5", "SPUS OUT5", "SPUS OUT5-SIFS5"},
{"SIFS5", "SPUS OUT6", "SPUS OUT6-SIFS5"},
{"SIFS5", "SPUS OUT7", "SPUS OUT7-SIFS5"},
{"SIFS5", "SPUS OUT8", "SPUS OUT8-SIFS5"},
{"SIFS5", "SPUS OUT9", "SPUS OUT9-SIFS5"},
{"SIFS5", "SPUS OUT10", "SPUS OUT10-SIFS5"},
{"SIFS5", "SPUS OUT11", "SPUS OUT11-SIFS5"},
{"SIFS0 OUT", "Switch", "SIFS0"},
{"SIFS1 OUT", "Switch", "SIFS1"},
{"SIFS2 OUT", "Switch", "SIFS2"},
{"SIFS3 OUT", "Switch", "SIFS3"},
{"SIFS4 OUT", "Switch", "SIFS4"},
{"SIFS5 OUT", "Switch", "SIFS5"},
{"UAIF0 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF0 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF0 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF0 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF0 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF0 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF0 SPK", "SIFMS", "SIFMS"},
{"UAIF1 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF1 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF1 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF1 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF1 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF1 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF1 SPK", "SIFMS", "SIFMS"},
{"UAIF2 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF2 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF2 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF2 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF2 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF2 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF2 SPK", "SIFMS", "SIFMS"},
{"UAIF3 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF3 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF3 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF3 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF3 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF3 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF3 SPK", "SIFMS", "SIFMS"},
{"UAIF4 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF4 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF4 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF4 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF4 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF4 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF4 SPK", "SIFMS", "SIFMS"},
{"UAIF5 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF5 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF5 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF5 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF5 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF5 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF5 SPK", "SIFMS", "SIFMS"},
{"UAIF6 SPK", "SIFS0", "SIFS0 OUT"},
{"UAIF6 SPK", "SIFS1", "SIFS1 OUT"},
{"UAIF6 SPK", "SIFS2", "SIFS2 OUT"},
{"UAIF6 SPK", "SIFS3", "SIFS3 OUT"},
{"UAIF6 SPK", "SIFS4", "SIFS4 OUT"},
{"UAIF6 SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF6 SPK", "SIFMS", "SIFMS"},
{"DSIF SPK", "SIFS1", "SIFS1 OUT"},
{"DSIF SPK", "SIFS2", "SIFS2 OUT"},
{"DSIF SPK", "SIFS3", "SIFS3 OUT"},
{"DSIF SPK", "SIFS4", "SIFS4 OUT"},
{"DSIF SPK", "SIFS5", "SIFS5 OUT"},
{"UAIF0 PLA", "UAIF0 Switch", "UAIF0 SPK"},
{"UAIF1 PLA", "UAIF1 Switch", "UAIF1 SPK"},
{"UAIF2 PLA", "UAIF2 Switch", "UAIF2 SPK"},
{"UAIF3 PLA", "UAIF3 Switch", "UAIF3 SPK"},
{"UAIF4 PLA", "UAIF4 Switch", "UAIF4 SPK"},
{"UAIF5 PLA", "UAIF5 Switch", "UAIF5 SPK"},
{"UAIF6 PLA", "UAIF6 Switch", "UAIF6 SPK"},
{"DSIF PLA", "DSIF Switch", "DSIF SPK"},
{"SIFS0", NULL, "SIFS0 Capture"},
{"SIFS1", NULL, "SIFS1 Capture"},
{"SIFS2", NULL, "SIFS2 Capture"},
{"SIFS3", NULL, "SIFS3 Capture"},
{"SIFS4", NULL, "SIFS4 Capture"},
{"SIFS5", NULL, "SIFS5 Capture"},
{"NSRC0 Playback", NULL, "NSRC0"},
{"NSRC1 Playback", NULL, "NSRC1"},
{"NSRC2 Playback", NULL, "NSRC2"},
{"NSRC3 Playback", NULL, "NSRC3"},
{"NSRC4 Playback", NULL, "NSRC4"},
{"NSRC0", NULL, "NSRC0 Capture"},
{"NSRC1", NULL, "NSRC1 Capture"},
{"NSRC2", NULL, "NSRC2 Capture"},
{"NSRC3", NULL, "NSRC3 Capture"},
{"NSRC4", NULL, "NSRC4 Capture"},
{"NSRC0", "SIFS0", "SIFS0 OUT"},
{"NSRC0", "SIFS1", "SIFS1 OUT"},
{"NSRC0", "SIFS2", "SIFS2 OUT"},
{"NSRC0", "SIFS3", "SIFS3 OUT"},
{"NSRC0", "SIFS4", "SIFS4 OUT"},
{"NSRC0", "SIFS5", "SIFS5 OUT"},
{"NSRC0", "UAIF0", "UAIF0 CAP"},
{"NSRC0", "UAIF1", "UAIF1 CAP"},
{"NSRC0", "UAIF2", "UAIF2 CAP"},
{"NSRC0", "UAIF3", "UAIF3 CAP"},
{"NSRC0", "UAIF4", "UAIF4 CAP"},
{"NSRC0", "UAIF5", "UAIF5 CAP"},
{"NSRC0", "UAIF6", "UAIF6 CAP"},
{"NSRC0", "SPDY", "SPDY CAP"},
{"NSRC1", "SIFS0", "SIFS0 OUT"},
{"NSRC1", "SIFS1", "SIFS1 OUT"},
{"NSRC1", "SIFS2", "SIFS2 OUT"},
{"NSRC1", "SIFS3", "SIFS3 OUT"},
{"NSRC1", "SIFS4", "SIFS4 OUT"},
{"NSRC1", "SIFS5", "SIFS5 OUT"},
{"NSRC1", "UAIF0", "UAIF0 CAP"},
{"NSRC1", "UAIF1", "UAIF1 CAP"},
{"NSRC1", "UAIF2", "UAIF2 CAP"},
{"NSRC1", "UAIF3", "UAIF3 CAP"},
{"NSRC1", "UAIF4", "UAIF4 CAP"},
{"NSRC1", "UAIF5", "UAIF5 CAP"},
{"NSRC1", "UAIF6", "UAIF6 CAP"},
{"NSRC1", "SPDY", "SPDY CAP"},
{"NSRC2", "SIFS0", "SIFS0 OUT"},
{"NSRC2", "SIFS1", "SIFS1 OUT"},
{"NSRC2", "SIFS2", "SIFS2 OUT"},
{"NSRC2", "SIFS3", "SIFS3 OUT"},
{"NSRC2", "SIFS4", "SIFS4 OUT"},
{"NSRC2", "SIFS5", "SIFS5 OUT"},
{"NSRC2", "UAIF0", "UAIF0 CAP"},
{"NSRC2", "UAIF1", "UAIF1 CAP"},
{"NSRC2", "UAIF2", "UAIF2 CAP"},
{"NSRC2", "UAIF3", "UAIF3 CAP"},
{"NSRC2", "UAIF4", "UAIF4 CAP"},
{"NSRC2", "UAIF5", "UAIF5 CAP"},
{"NSRC2", "UAIF6", "UAIF6 CAP"},
{"NSRC2", "SPDY", "SPDY CAP"},
{"NSRC3", "SIFS0", "SIFS0 OUT"},
{"NSRC3", "SIFS1", "SIFS1 OUT"},
{"NSRC3", "SIFS2", "SIFS2 OUT"},
{"NSRC3", "SIFS3", "SIFS3 OUT"},
{"NSRC3", "SIFS4", "SIFS4 OUT"},
{"NSRC3", "SIFS5", "SIFS5 OUT"},
{"NSRC3", "UAIF0", "UAIF0 CAP"},
{"NSRC3", "UAIF1", "UAIF1 CAP"},
{"NSRC3", "UAIF2", "UAIF2 CAP"},
{"NSRC3", "UAIF3", "UAIF3 CAP"},
{"NSRC3", "UAIF4", "UAIF4 CAP"},
{"NSRC3", "UAIF5", "UAIF5 CAP"},
{"NSRC3", "UAIF6", "UAIF6 CAP"},
{"NSRC3", "SPDY", "SPDY CAP"},
{"NSRC4", "SIFS0", "SIFS0 OUT"},
{"NSRC4", "SIFS1", "SIFS1 OUT"},
{"NSRC4", "SIFS2", "SIFS2 OUT"},
{"NSRC4", "SIFS3", "SIFS3 OUT"},
{"NSRC4", "SIFS4", "SIFS4 OUT"},
{"NSRC4", "SIFS5", "SIFS5 OUT"},
{"NSRC4", "UAIF0", "UAIF0 CAP"},
{"NSRC4", "UAIF1", "UAIF1 CAP"},
{"NSRC4", "UAIF2", "UAIF2 CAP"},
{"NSRC4", "UAIF3", "UAIF3 CAP"},
{"NSRC4", "UAIF4", "UAIF4 CAP"},
{"NSRC4", "UAIF5", "UAIF5 CAP"},
{"NSRC4", "UAIF6", "UAIF6 CAP"},
{"NSRC4", "SPDY", "SPDY CAP"},
{"SPUM ASRC0", NULL, "NSRC0"},
{"SPUM ASRC1", NULL, "NSRC1"},
{"SPUM ASRC2", NULL, "NSRC2"},
{"SPUM ASRC3", NULL, "NSRC3"},
{"SPUM ASRC4", NULL, "NSRC4"},
{"SIFM0", NULL, "SPUM ASRC0"},
{"SIFM1", NULL, "SPUM ASRC1"},
{"SIFM2", NULL, "SPUM ASRC2"},
{"SIFM3", NULL, "SPUM ASRC3"},
{"SIFM4", NULL, "SPUM ASRC4"},
{"SIFM0-SIFMS", "SIFMS", "SIFM0"},
{"SIFM1-SIFMS", "SIFMS", "SIFM1"},
{"SIFM2-SIFMS", "SIFMS", "SIFM2"},
{"SIFM3-SIFMS", "SIFMS", "SIFM3"},
{"SIFM4-SIFMS", "SIFMS", "SIFM4"},
{"SIFMS", "SIFM0", "SIFM0-SIFMS"},
{"SIFMS", "SIFM1", "SIFM1-SIFMS"},
{"SIFMS", "SIFM2", "SIFM2-SIFMS"},
{"SIFMS", "SIFM3", "SIFM3-SIFMS"},
{"SIFMS", "SIFM4", "SIFM4-SIFMS"},
};
static int cmpnt_probe(struct snd_soc_component *cmpnt)
{
struct device *dev = cmpnt->dev;
struct abox_data *data = dev_get_drvdata(dev);
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
abox_dbg(dev, "%s\n", __func__);
snd_soc_component_init_regmap(cmpnt, data->regmap);
snd_soc_add_component_controls(cmpnt, spus_asrc_controls,
ARRAY_SIZE(spus_asrc_controls));
snd_soc_add_component_controls(cmpnt, spum_asrc_controls,
ARRAY_SIZE(spum_asrc_controls));
snd_soc_add_component_controls(cmpnt, spus_asrc_id_controls,
ARRAY_SIZE(spus_asrc_id_controls));
snd_soc_add_component_controls(cmpnt, spum_asrc_id_controls,
ARRAY_SIZE(spum_asrc_id_controls));
snd_soc_add_component_controls(cmpnt, spus_asrc_apf_coef_controls,
ARRAY_SIZE(spus_asrc_apf_coef_controls));
snd_soc_add_component_controls(cmpnt, spum_asrc_apf_coef_controls,
ARRAY_SIZE(spum_asrc_apf_coef_controls));
snd_soc_add_component_controls(cmpnt, spus_asrc_os_controls,
ARRAY_SIZE(spus_asrc_os_controls));
snd_soc_add_component_controls(cmpnt, spus_asrc_is_controls,
ARRAY_SIZE(spus_asrc_is_controls));
snd_soc_add_component_controls(cmpnt, spum_asrc_os_controls,
ARRAY_SIZE(spum_asrc_os_controls));
snd_soc_add_component_controls(cmpnt, spum_asrc_is_controls,
ARRAY_SIZE(spum_asrc_is_controls));
snd_soc_add_component_controls(cmpnt, sidetone_controls,
ARRAY_SIZE(sidetone_controls));
snd_soc_dapm_add_routes(dapm, sidetone_routes,
ARRAY_SIZE(sidetone_routes));
snd_soc_dapm_weak_routes(dapm, sidetone_routes,
ARRAY_SIZE(sidetone_routes));
data->cmpnt = cmpnt;
/* vdma and dump are initialized in abox component probe
* to set vdma to sound card 1 and dump to sound card 2.
*/
abox_vdma_register_card(dev);
abox_dump_init(dev);
wakeup_source_init(&data->ws, "abox");
return 0;
}
static void cmpnt_remove(struct snd_soc_component *cmpnt)
{
struct device *dev = cmpnt->dev;
struct abox_data *data = dev_get_drvdata(dev);
abox_dbg(dev, "%s\n", __func__);
wakeup_source_trash(&data->ws);
}
static const struct snd_soc_component_driver abox_cmpnt_drv = {
.probe = cmpnt_probe,
.remove = cmpnt_remove,
.controls = cmpnt_controls,
.num_controls = ARRAY_SIZE(cmpnt_controls),
.dapm_widgets = cmpnt_widgets,
.num_dapm_widgets = ARRAY_SIZE(cmpnt_widgets),
.dapm_routes = cmpnt_routes,
.num_dapm_routes = ARRAY_SIZE(cmpnt_routes),
.probe_order = SND_SOC_COMP_ORDER_FIRST,
};
int abox_cmpnt_adjust_sbank(struct abox_data *data,
enum abox_dai id, struct snd_pcm_hw_params *params)
{
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int time, size, reg, val;
unsigned int mask = ABOX_SBANK_SIZE_MASK;
int ret;
switch (id) {
case ABOX_RDMA0:
case ABOX_RDMA1:
case ABOX_RDMA2:
case ABOX_RDMA3:
case ABOX_RDMA4:
case ABOX_RDMA5:
case ABOX_RDMA6:
case ABOX_RDMA7:
case ABOX_RDMA8:
case ABOX_RDMA9:
case ABOX_RDMA10:
case ABOX_RDMA11:
reg = ABOX_SPUS_SBANK_RDMA(id - ABOX_RDMA0);
break;
case ABOX_RDMA0_BE:
case ABOX_RDMA1_BE:
case ABOX_RDMA2_BE:
case ABOX_RDMA3_BE:
case ABOX_RDMA4_BE:
case ABOX_RDMA5_BE:
case ABOX_RDMA6_BE:
case ABOX_RDMA7_BE:
case ABOX_RDMA8_BE:
case ABOX_RDMA9_BE:
case ABOX_RDMA10_BE:
case ABOX_RDMA11_BE:
reg = ABOX_SPUS_SBANK_RDMA(id - ABOX_RDMA0_BE);
break;
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
reg = ABOX_SPUM_SBANK_NSRC(id - ABOX_NSRC0);
break;
default:
return -EINVAL;
}
time = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME)->min;
time /= 1000;
if (time <= 10)
size = SZ_128;
else
size = SZ_512;
/* Sbank size unit is 16byte(= 4 shifts) */
val = size << (ABOX_SBANK_SIZE_L - 4);
abox_info(cmpnt->dev, "%s(%#x, %ums): %u\n", __func__, id, time, size);
ret = snd_soc_component_update_bits(cmpnt, reg, mask, val);
if (ret < 0) {
abox_err(cmpnt->dev, "sbank write error: %d\n", ret);
return ret;
}
return size;
}
int abox_cmpnt_reset_cnt_val(struct abox_data *data, enum abox_dai id)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int idx, val, sifs_id;
int ret = 0;
abox_dbg(dev, "%s(%#x)\n", __func__, id);
ret = snd_soc_component_read(cmpnt, ABOX_ROUTE_CTRL0, &val);
if (ret < 0)
return ret;
switch (id) {
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
idx = id - ABOX_UAIF0;
sifs_id = val & ABOX_ROUTE_UAIF_SPK_MASK(idx);
sifs_id = (sifs_id >> ABOX_ROUTE_UAIF_SPK_L(idx)) - 1;
break;
case ABOX_DSIF:
sifs_id = val & ABOX_ROUTE_DSIF_MASK;
sifs_id = (sifs_id >> ABOX_ROUTE_DSIF_L) - 1;
break;
default:
return -EINVAL;
}
if (sifs_id < 12) {
ret = snd_soc_component_write(cmpnt,
ABOX_SPUS_CTRL_SIFS_CNT(sifs_id), 0);
if (ret < 0)
return ret;
abox_info(dev, "reset sifs%d_cnt_val\n", sifs_id);
}
return ret;
}
static int sifs_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct abox_data *data = dev_get_drvdata(dev);
int ret = 0;
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
goto out;
ret = set_cnt_val(data, dai, params);
out:
return ret;
}
static const struct snd_soc_dai_ops sifs_dai_ops = {
.hw_params = sifs_hw_params,
};
static int src_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
enum abox_dai id = dai->id;
struct abox_data *data = snd_soc_component_get_drvdata(dai->component);
int ret = 0;
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
return 0;
abox_dbg(dev, "%s[%#x]\n", __func__, id);
ret = abox_cmpnt_adjust_sbank(data, id, params);
if (ret < 0)
return ret;
return 0;
}
static const struct snd_soc_dai_ops src_dai_ops = {
.hw_params = src_hw_params,
};
static struct snd_soc_dai_driver abox_cmpnt_dai_drv[] = {
{
.name = "SIFS0",
.id = ABOX_SIFS0,
.capture = {
.stream_name = "SIFS0 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "SIFS1",
.id = ABOX_SIFS1,
.capture = {
.stream_name = "SIFS1 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "SIFS2",
.id = ABOX_SIFS2,
.capture = {
.stream_name = "SIFS2 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "SIFS3",
.id = ABOX_SIFS3,
.capture = {
.stream_name = "SIFS3 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "SIFS4",
.id = ABOX_SIFS4,
.capture = {
.stream_name = "SIFS4 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "SIFS5",
.id = ABOX_SIFS5,
.capture = {
.stream_name = "SIFS5 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &sifs_dai_ops,
},
{
.name = "NSRC0",
.id = ABOX_NSRC0,
.playback = {
.stream_name = "NSRC0 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC0 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC1",
.id = ABOX_NSRC1,
.playback = {
.stream_name = "NSRC1 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC1 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC2",
.id = ABOX_NSRC2,
.playback = {
.stream_name = "NSRC2 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC2 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC3",
.id = ABOX_NSRC3,
.playback = {
.stream_name = "NSRC3 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC3 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC4",
.id = ABOX_NSRC4,
.playback = {
.stream_name = "NSRC4 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC4 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC5",
.id = ABOX_NSRC5,
.playback = {
.stream_name = "NSRC5 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC5 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC6",
.id = ABOX_NSRC6,
.playback = {
.stream_name = "NSRC6 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC6 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "NSRC7",
.id = ABOX_NSRC7,
.playback = {
.stream_name = "NSRC7 Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "NSRC7 Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.ops = &src_dai_ops,
},
{
.name = "USB",
.id = ABOX_USB,
.playback = {
.stream_name = "USB Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "USB Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
},
{
.name = "FWD",
.id = ABOX_FWD,
.playback = {
.stream_name = "FWD Playback",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
.capture = {
.stream_name = "FWD Capture",
.channels_min = 1,
.channels_max = 8,
.rates = ABOX_SAMPLING_RATES,
.rate_min = 8000,
.rate_max = 384000,
.formats = ABOX_SAMPLE_FORMATS,
},
},
};
int abox_cmpnt_update_cnt_val(struct device *adev)
{
/* nothing to do anymore */
return 0;
}
int abox_cmpnt_hw_params_fixup_helper(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_soc_dai *dai = rtd->cpu_dai;
struct device *dev = dai->dev;
int ret;
abox_dbg(dev, "%s(%s)\n", __func__, dai->name);
switch (dai->id) {
case ABOX_RDMA0:
case ABOX_RDMA1:
case ABOX_RDMA2:
case ABOX_RDMA3:
case ABOX_RDMA4:
case ABOX_RDMA5:
case ABOX_RDMA6:
case ABOX_RDMA7:
case ABOX_RDMA8:
case ABOX_RDMA9:
case ABOX_RDMA10:
case ABOX_RDMA11:
ret = rdma_hw_params_fixup(dai, params);
break;
case ABOX_UAIF0:
case ABOX_UAIF1:
case ABOX_UAIF2:
case ABOX_UAIF3:
case ABOX_UAIF4:
case ABOX_UAIF5:
case ABOX_UAIF6:
case ABOX_SPDY:
ret = abox_if_hw_params_fixup(dai, params);
break;
case ABOX_SIFS0:
case ABOX_SIFS1:
case ABOX_SIFS2:
case ABOX_SIFS3:
case ABOX_SIFS4:
case ABOX_SIFS5:
ret = sifs_hw_params_fixup(dai, params);
break;
case ABOX_NSRC0:
case ABOX_NSRC1:
case ABOX_NSRC2:
case ABOX_NSRC3:
case ABOX_NSRC4:
case ABOX_NSRC5:
case ABOX_NSRC6:
case ABOX_NSRC7:
ret = sifm_hw_params_fixup(dai, params);
break;
case ABOX_RDMA0_BE:
case ABOX_RDMA1_BE:
case ABOX_RDMA2_BE:
case ABOX_RDMA3_BE:
case ABOX_RDMA4_BE:
case ABOX_RDMA5_BE:
case ABOX_RDMA6_BE:
case ABOX_RDMA7_BE:
case ABOX_RDMA8_BE:
case ABOX_RDMA9_BE:
case ABOX_RDMA10_BE:
case ABOX_RDMA11_BE:
ret = rdma_be_hw_params_fixup(rtd, params);
break;
case ABOX_WDMA0_BE:
case ABOX_WDMA1_BE:
case ABOX_WDMA2_BE:
case ABOX_WDMA3_BE:
case ABOX_WDMA4_BE:
case ABOX_WDMA5_BE:
case ABOX_WDMA6_BE:
case ABOX_WDMA7_BE:
ret = wdma_be_hw_params_fixup(rtd, params);
break;
default:
abox_err(dev, "invalid hw_params fixup request\n");
ret = -EINVAL;
break;
}
return ret;
}
static int register_if_routes(struct device *dev,
const struct snd_soc_dapm_route *route_base, int num,
struct snd_soc_dapm_context *dapm, const char *name)
{
struct snd_soc_dapm_route *route;
int i;
route = devm_kmemdup(dev, route_base, sizeof(*route_base) * num,
GFP_KERNEL);
if (!route)
return -ENOMEM;
for (i = 0; i < num; i++) {
if (route[i].sink)
route[i].sink = devm_kasprintf(dev, GFP_KERNEL,
route[i].sink, name);
if (route[i].control)
route[i].control = devm_kasprintf(dev, GFP_KERNEL,
route[i].control, name);
if (route[i].source)
route[i].source = devm_kasprintf(dev, GFP_KERNEL,
route[i].source, name);
}
snd_soc_dapm_add_routes(dapm, route, num);
devm_kfree(dev, route);
return 0;
}
static const struct snd_soc_dapm_route route_base_if_pla[] = {
/* sink, control, source */
{"%s Playback", NULL, "%s PLA"},
};
static const struct snd_soc_dapm_route route_base_if_cap[] = {
/* sink, control, source */
{"SPUSM", "%s", "%s CAP"},
{"SPUST", "%s", "%s CAP"},
{"%s CAP", "%s Switch", "%s Capture"},
};
int abox_cmpnt_register_if(struct device *dev_abox,
struct device *dev, unsigned int id, const char *name,
bool playback, bool capture)
{
struct abox_data *data = dev_get_drvdata(dev_abox);
struct snd_soc_dapm_context *dapm;
int ret;
if (id >= ARRAY_SIZE(data->dev_if)) {
abox_err(dev, "%s: invalid id(%u)\n", __func__, id);
return -EINVAL;
}
dapm = snd_soc_component_get_dapm(data->cmpnt);
data->dev_if[id] = dev;
if (id > data->if_count)
data->if_count = id + 1;
if (playback) {
ret = register_if_routes(dev, route_base_if_pla,
ARRAY_SIZE(route_base_if_pla), dapm, name);
if (ret < 0)
return ret;
}
if (capture) {
ret = register_if_routes(dev, route_base_if_cap,
ARRAY_SIZE(route_base_if_cap), dapm, name);
if (ret < 0)
return ret;
}
return 0;
}
static int register_rdma_routes(struct device *dev,
const struct snd_soc_dapm_route *route_base, int num,
struct snd_soc_dapm_context *dapm, const char *name, int id)
{
struct snd_soc_dapm_route *route;
int i;
route = kmemdup(route_base, sizeof(*route_base) * num,
GFP_KERNEL);
if (!route)
return -ENOMEM;
for (i = 0; i < num; i++) {
if (route[i].sink)
route[i].sink = devm_kasprintf(dev, GFP_KERNEL,
route[i].sink, id);
if (route[i].control)
route[i].control = devm_kasprintf(dev, GFP_KERNEL,
route[i].control);
if (route[i].source)
route[i].source = devm_kasprintf(dev, GFP_KERNEL,
route[i].source, name);
}
snd_soc_dapm_add_routes(dapm, route, num);
kfree(route);
return 0;
}
static const struct snd_soc_dapm_route route_base_rdma[] = {
/* sink, control, source */
{"SPUS IN%d", NULL, "%s Playback"},
};
int abox_cmpnt_register_rdma(struct device *dev_abox,
struct device *dev, unsigned int id, const char *name)
{
struct abox_data *data = dev_get_drvdata(dev_abox);
struct snd_soc_component *cmpnt = data->cmpnt;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
if (id >= ARRAY_SIZE(data->dev_rdma)) {
abox_err(dev, "%s: invalid id(%u)\n", __func__, id);
return -EINVAL;
}
data->dev_rdma[id] = dev;
if (id > data->rdma_count)
data->rdma_count = id + 1;
return register_rdma_routes(dev, route_base_rdma, 1, dapm, name, id);
}
static int register_wdma_routes(struct device *dev,
const struct snd_soc_dapm_route *route_base, int num,
struct snd_soc_dapm_context *dapm, const char *name, int id)
{
struct snd_soc_dapm_route *route;
int i;
route = kmemdup(route_base, sizeof(*route_base) * num,
GFP_KERNEL);
if (!route)
return -ENOMEM;
for (i = 0; i < num; i++) {
if (route[i].sink)
route[i].sink = devm_kasprintf(dev, GFP_KERNEL,
route[i].sink, name);
if (route[i].control)
route[i].control = devm_kasprintf(dev, GFP_KERNEL,
route[i].control);
if (route[i].source)
route[i].source = devm_kasprintf(dev, GFP_KERNEL,
route[i].source, id);
}
snd_soc_dapm_add_routes(dapm, route, num);
kfree(route);
return 0;
}
static const struct snd_soc_dapm_route route_base_wdma[] = {
/* sink, control, source */
{"%s Capture", "WDMA", "SIFM%d"},
};
int abox_cmpnt_register_wdma(struct device *dev_abox,
struct device *dev, unsigned int id, const char *name)
{
struct abox_data *data = dev_get_drvdata(dev_abox);
struct snd_soc_component *cmpnt = data->cmpnt;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
if (id >= ARRAY_SIZE(data->dev_wdma)) {
abox_err(dev, "%s: invalid id(%u)\n", __func__, id);
return -EINVAL;
}
data->dev_wdma[id] = dev;
if (id > data->wdma_count)
data->wdma_count = id + 1;
return register_wdma_routes(dev, route_base_wdma, 1, dapm, name, id);
}
int abox_cmpnt_restore(struct device *adev)
{
struct abox_data *data = dev_get_drvdata(adev);
int i;
abox_dbg(adev, "%s\n", __func__);
for (i = SET_SIFS0_RATE; i <= SET_SIFM7_RATE; i++)
rate_put_ipc(adev, 0, i);
for (i = SET_SIFS0_FORMAT; i <= SET_SIFM7_FORMAT; i++)
format_put_ipc(adev, 0, 0, i);
if (s_default)
asrc_factor_put_ipc(adev, s_default, SET_ASRC_FACTOR_CP);
if (data->audio_mode)
audio_mode_put_ipc(adev, data->audio_mode);
if (data->sound_type)
sound_type_put_ipc(adev, data->sound_type);
return 0;
}
int abox_cmpnt_register(struct device *adev)
{
const struct snd_soc_component_driver *cmpnt_drv;
struct snd_soc_dai_driver *dai_drv;
int num_dai;
cmpnt_drv = &abox_cmpnt_drv;
dai_drv = abox_cmpnt_dai_drv;
num_dai = ARRAY_SIZE(abox_cmpnt_dai_drv);
return snd_soc_register_component(adev, cmpnt_drv, dai_drv, num_dai);
}