cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tda7419.c (21988B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * TDA7419 audio processor driver
      4 *
      5 * Copyright 2018 Konsulko Group
      6 *
      7 * Author: Matt Porter <mporter@konsulko.com>
      8 */
      9
     10#include <linux/i2c.h>
     11#include <linux/init.h>
     12#include <linux/module.h>
     13#include <linux/regmap.h>
     14#include <sound/core.h>
     15#include <sound/control.h>
     16#include <sound/soc.h>
     17#include <sound/tlv.h>
     18
     19#define TDA7419_MAIN_SRC_REG		0x00
     20#define TDA7419_LOUDNESS_REG		0x01
     21#define TDA7419_MUTE_CLK_REG		0x02
     22#define TDA7419_VOLUME_REG		0x03
     23#define TDA7419_TREBLE_REG		0x04
     24#define TDA7419_MIDDLE_REG		0x05
     25#define TDA7419_BASS_REG		0x06
     26#define TDA7419_SECOND_SRC_REG		0x07
     27#define TDA7419_SUB_MID_BASS_REG	0x08
     28#define TDA7419_MIXING_GAIN_REG		0x09
     29#define TDA7419_ATTENUATOR_LF_REG	0x0a
     30#define TDA7419_ATTENUATOR_RF_REG	0x0b
     31#define TDA7419_ATTENUATOR_LR_REG	0x0c
     32#define TDA7419_ATTENUATOR_RR_REG	0x0d
     33#define TDA7419_MIXING_LEVEL_REG	0x0e
     34#define TDA7419_ATTENUATOR_SUB_REG	0x0f
     35#define TDA7419_SA_CLK_AC_REG		0x10
     36#define TDA7419_TESTING_REG		0x11
     37
     38#define TDA7419_MAIN_SRC_SEL		0
     39#define TDA7419_MAIN_SRC_GAIN		3
     40#define TDA7419_MAIN_SRC_AUTOZERO	7
     41
     42#define TDA7419_LOUDNESS_ATTEN		0
     43#define TDA7419_LOUDNESS_CENTER_FREQ	4
     44#define TDA7419_LOUDNESS_BOOST		6
     45#define TDA7419_LOUDNESS_SOFT_STEP	7
     46
     47#define TDA7419_VOLUME_SOFT_STEP	7
     48
     49#define TDA7419_SOFT_MUTE		0
     50#define TDA7419_MUTE_INFLUENCE		1
     51#define TDA7419_SOFT_MUTE_TIME		2
     52#define TDA7419_SOFT_STEP_TIME		4
     53#define TDA7419_CLK_FAST_MODE		7
     54
     55#define TDA7419_TREBLE_CENTER_FREQ	5
     56#define TDA7419_REF_OUT_SELECT		7
     57
     58#define TDA7419_MIDDLE_Q_FACTOR		5
     59#define TDA7419_MIDDLE_SOFT_STEP	7
     60
     61#define TDA7419_BASS_Q_FACTOR		5
     62#define TDA7419_BASS_SOFT_STEP		7
     63
     64#define TDA7419_SECOND_SRC_SEL		0
     65#define TDA7419_SECOND_SRC_GAIN		3
     66#define TDA7419_REAR_SPKR_SRC		7
     67
     68#define TDA7419_SUB_CUT_OFF_FREQ	0
     69#define TDA7419_MIDDLE_CENTER_FREQ	2
     70#define TDA7419_BASS_CENTER_FREQ	4
     71#define TDA7419_BASS_DC_MODE		6
     72#define TDA7419_SMOOTHING_FILTER	7
     73
     74#define TDA7419_MIX_LF			0
     75#define TDA7419_MIX_RF			1
     76#define TDA7419_MIX_ENABLE		2
     77#define TDA7419_SUB_ENABLE		3
     78#define TDA7419_HPF_GAIN		4
     79
     80#define TDA7419_SA_Q_FACTOR		0
     81#define TDA7419_RESET_MODE		1
     82#define TDA7419_SA_SOURCE		2
     83#define TDA7419_SA_RUN			3
     84#define TDA7419_RESET			4
     85#define TDA7419_CLK_SOURCE		5
     86#define TDA7419_COUPLING_MODE		6
     87
     88struct tda7419_data {
     89	struct regmap *regmap;
     90};
     91
     92static bool tda7419_readable_reg(struct device *dev, unsigned int reg)
     93{
     94	return false;
     95}
     96
     97static const struct reg_default tda7419_regmap_defaults[] = {
     98	{ TDA7419_MAIN_SRC_REG,	0xfe },
     99	{ TDA7419_LOUDNESS_REG, 0xfe },
    100	{ TDA7419_MUTE_CLK_REG, 0xfe },
    101	{ TDA7419_VOLUME_REG, 0xfe },
    102	{ TDA7419_TREBLE_REG, 0xfe },
    103	{ TDA7419_MIDDLE_REG, 0xfe },
    104	{ TDA7419_BASS_REG, 0xfe },
    105	{ TDA7419_SECOND_SRC_REG, 0xfe },
    106	{ TDA7419_SUB_MID_BASS_REG, 0xfe },
    107	{ TDA7419_MIXING_GAIN_REG, 0xfe },
    108	{ TDA7419_ATTENUATOR_LF_REG, 0xfe },
    109	{ TDA7419_ATTENUATOR_RF_REG, 0xfe },
    110	{ TDA7419_ATTENUATOR_LR_REG, 0xfe },
    111	{ TDA7419_ATTENUATOR_RR_REG, 0xfe },
    112	{ TDA7419_MIXING_LEVEL_REG, 0xfe },
    113	{ TDA7419_ATTENUATOR_SUB_REG, 0xfe },
    114	{ TDA7419_SA_CLK_AC_REG, 0xfe },
    115	{ TDA7419_TESTING_REG, 0xfe },
    116};
    117
    118static const struct regmap_config tda7419_regmap_config = {
    119	.reg_bits = 8,
    120	.val_bits = 8,
    121	.max_register = TDA7419_TESTING_REG,
    122	.cache_type = REGCACHE_RBTREE,
    123	.readable_reg = tda7419_readable_reg,
    124	.reg_defaults = tda7419_regmap_defaults,
    125	.num_reg_defaults = ARRAY_SIZE(tda7419_regmap_defaults),
    126};
    127
    128struct tda7419_vol_control {
    129	int min, max;
    130	unsigned int reg, rreg, mask, thresh;
    131	unsigned int invert:1;
    132};
    133
    134static inline bool tda7419_vol_is_stereo(struct tda7419_vol_control *tvc)
    135{
    136	if (tvc->reg == tvc->rreg)
    137		return false;
    138
    139	return true;
    140}
    141
    142static int tda7419_vol_info(struct snd_kcontrol *kcontrol,
    143	struct snd_ctl_elem_info *uinfo)
    144{
    145	struct tda7419_vol_control *tvc =
    146		(struct tda7419_vol_control *)kcontrol->private_value;
    147
    148	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    149	uinfo->count = tda7419_vol_is_stereo(tvc) ? 2 : 1;
    150	uinfo->value.integer.min = tvc->min;
    151	uinfo->value.integer.max = tvc->max;
    152
    153	return 0;
    154}
    155
    156static inline int tda7419_vol_get_value(int val, unsigned int mask,
    157					int min, int thresh,
    158					unsigned int invert)
    159{
    160	val &= mask;
    161	if (val < thresh) {
    162		if (invert)
    163			val = 0 - val;
    164	} else if (val > thresh) {
    165		if (invert)
    166			val = val - thresh;
    167		else
    168			val = thresh - val;
    169	}
    170
    171	if (val < min)
    172		val = min;
    173
    174	return val;
    175}
    176
    177static int tda7419_vol_get(struct snd_kcontrol *kcontrol,
    178			   struct snd_ctl_elem_value *ucontrol)
    179{
    180	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
    181	struct tda7419_vol_control *tvc =
    182		(struct tda7419_vol_control *)kcontrol->private_value;
    183	unsigned int reg = tvc->reg;
    184	unsigned int rreg = tvc->rreg;
    185	unsigned int mask = tvc->mask;
    186	int min = tvc->min;
    187	int thresh = tvc->thresh;
    188	unsigned int invert = tvc->invert;
    189	int val;
    190
    191	val = snd_soc_component_read(component, reg);
    192	ucontrol->value.integer.value[0] =
    193		tda7419_vol_get_value(val, mask, min, thresh, invert);
    194
    195	if (tda7419_vol_is_stereo(tvc)) {
    196		val = snd_soc_component_read(component, rreg);
    197		ucontrol->value.integer.value[1] =
    198			tda7419_vol_get_value(val, mask, min, thresh, invert);
    199	}
    200
    201	return 0;
    202}
    203
    204static inline int tda7419_vol_put_value(int val, int thresh,
    205					unsigned int invert)
    206{
    207	if (val < 0) {
    208		if (invert)
    209			val = abs(val);
    210		else
    211			val = thresh - val;
    212	} else if ((val > 0) && invert) {
    213		val += thresh;
    214	}
    215
    216	return val;
    217}
    218
    219static int tda7419_vol_put(struct snd_kcontrol *kcontrol,
    220			   struct snd_ctl_elem_value *ucontrol)
    221{
    222	struct snd_soc_component *component =
    223		snd_kcontrol_chip(kcontrol);
    224	struct tda7419_vol_control *tvc =
    225		(struct tda7419_vol_control *)kcontrol->private_value;
    226	unsigned int reg = tvc->reg;
    227	unsigned int rreg = tvc->rreg;
    228	unsigned int mask = tvc->mask;
    229	int thresh = tvc->thresh;
    230	unsigned int invert = tvc->invert;
    231	int val;
    232	int ret;
    233
    234	val = tda7419_vol_put_value(ucontrol->value.integer.value[0],
    235				    thresh, invert);
    236	ret = snd_soc_component_update_bits(component, reg,
    237					    mask, val);
    238	if (ret < 0)
    239		return ret;
    240
    241	if (tda7419_vol_is_stereo(tvc)) {
    242		val = tda7419_vol_put_value(ucontrol->value.integer.value[1],
    243					    thresh, invert);
    244		ret = snd_soc_component_update_bits(component, rreg,
    245						    mask, val);
    246	}
    247
    248	return ret;
    249}
    250
    251#define TDA7419_SINGLE_VALUE(xreg, xmask, xmin, xmax, xthresh, xinvert) \
    252	((unsigned long)&(struct tda7419_vol_control) \
    253	{.reg = xreg, .rreg = xreg, .mask = xmask, .min = xmin, \
    254	 .max = xmax, .thresh = xthresh, .invert = xinvert})
    255
    256#define TDA7419_DOUBLE_R_VALUE(xregl, xregr, xmask, xmin, xmax, xthresh, \
    257			       xinvert) \
    258	((unsigned long)&(struct tda7419_vol_control) \
    259	{.reg = xregl, .rreg = xregr, .mask = xmask, .min = xmin, \
    260	 .max = xmax, .thresh = xthresh, .invert = xinvert})
    261
    262#define TDA7419_SINGLE_TLV(xname, xreg, xmask, xmin, xmax, xthresh, \
    263			   xinvert, xtlv_array) \
    264{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
    265	.name = xname, \
    266	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
    267		SNDRV_CTL_ELEM_ACCESS_READWRITE, \
    268	.tlv.p = (xtlv_array), \
    269	.info = tda7419_vol_info, \
    270	.get = tda7419_vol_get, \
    271	.put = tda7419_vol_put, \
    272	.private_value = TDA7419_SINGLE_VALUE(xreg, xmask, xmin, \
    273					      xmax, xthresh, xinvert), \
    274}
    275
    276#define TDA7419_DOUBLE_R_TLV(xname, xregl, xregr, xmask, xmin, xmax, \
    277			     xthresh, xinvert, xtlv_array) \
    278{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
    279	.name = xname, \
    280	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
    281		SNDRV_CTL_ELEM_ACCESS_READWRITE, \
    282	.tlv.p = (xtlv_array), \
    283	.info = tda7419_vol_info, \
    284	.get = tda7419_vol_get, \
    285	.put = tda7419_vol_put, \
    286	.private_value = TDA7419_DOUBLE_R_VALUE(xregl, xregr, xmask, \
    287						xmin, xmax, xthresh, \
    288						xinvert), \
    289}
    290
    291static const char * const enum_src_sel[] = {
    292	"QD", "SE1", "SE2", "SE3", "SE", "Mute", "Mute", "Mute"};
    293static SOC_ENUM_SINGLE_DECL(soc_enum_main_src_sel,
    294	TDA7419_MAIN_SRC_REG, TDA7419_MAIN_SRC_SEL, enum_src_sel);
    295static const struct snd_kcontrol_new soc_mux_main_src_sel =
    296	SOC_DAPM_ENUM("Main Source Select", soc_enum_main_src_sel);
    297static DECLARE_TLV_DB_SCALE(tlv_src_gain, 0, 100, 0);
    298static DECLARE_TLV_DB_SCALE(tlv_loudness_atten, -1500, 100, 0);
    299static const char * const enum_loudness_center_freq[] = {
    300	"Flat", "400 Hz", "800 Hz", "2400 Hz"};
    301static SOC_ENUM_SINGLE_DECL(soc_enum_loudness_center_freq,
    302	TDA7419_LOUDNESS_REG, TDA7419_LOUDNESS_CENTER_FREQ,
    303	enum_loudness_center_freq);
    304static const char * const enum_mute_influence[] = {
    305	"Pin and IIC", "IIC"};
    306static SOC_ENUM_SINGLE_DECL(soc_enum_mute_influence,
    307	TDA7419_MUTE_CLK_REG, TDA7419_MUTE_INFLUENCE, enum_mute_influence);
    308static const char * const enum_soft_mute_time[] = {
    309	"0.48 ms", "0.96 ms", "123 ms", "123 ms"};
    310static SOC_ENUM_SINGLE_DECL(soc_enum_soft_mute_time,
    311	TDA7419_MUTE_CLK_REG, TDA7419_SOFT_MUTE_TIME, enum_soft_mute_time);
    312static const char * const enum_soft_step_time[] = {
    313	"0.160 ms", "0.321 ms", "0.642 ms", "1.28 ms",
    314	"2.56 ms", "5.12 ms", "10.24 ms", "20.48 ms"};
    315static SOC_ENUM_SINGLE_DECL(soc_enum_soft_step_time,
    316	TDA7419_MUTE_CLK_REG, TDA7419_SOFT_STEP_TIME, enum_soft_step_time);
    317static DECLARE_TLV_DB_SCALE(tlv_volume, -8000, 100, 1);
    318static const char * const enum_treble_center_freq[] = {
    319	"10.0 kHz", "12.5 kHz", "15.0 kHz", "17.5 kHz"};
    320static DECLARE_TLV_DB_SCALE(tlv_filter, -1500, 100, 0);
    321static SOC_ENUM_SINGLE_DECL(soc_enum_treble_center_freq,
    322	TDA7419_TREBLE_REG, TDA7419_TREBLE_CENTER_FREQ,
    323	enum_treble_center_freq);
    324static const char * const enum_ref_out_select[] = {
    325	"External Vref (4 V)", "Internal Vref (3.3 V)"};
    326static SOC_ENUM_SINGLE_DECL(soc_enum_ref_out_select,
    327	TDA7419_TREBLE_REG, TDA7419_REF_OUT_SELECT, enum_ref_out_select);
    328static const char * const enum_middle_q_factor[] = {
    329	"0.5", "0.75", "1.0", "1.25"};
    330static SOC_ENUM_SINGLE_DECL(soc_enum_middle_q_factor,
    331	TDA7419_MIDDLE_REG, TDA7419_MIDDLE_Q_FACTOR, enum_middle_q_factor);
    332static const char * const enum_bass_q_factor[] = {
    333	"1.0", "1.25", "1.5", "2.0"};
    334static SOC_ENUM_SINGLE_DECL(soc_enum_bass_q_factor,
    335	TDA7419_BASS_REG, TDA7419_BASS_Q_FACTOR, enum_bass_q_factor);
    336static SOC_ENUM_SINGLE_DECL(soc_enum_second_src_sel,
    337	TDA7419_SECOND_SRC_REG, TDA7419_SECOND_SRC_SEL, enum_src_sel);
    338static const struct snd_kcontrol_new soc_mux_second_src_sel =
    339	SOC_DAPM_ENUM("Second Source Select", soc_enum_second_src_sel);
    340static const char * const enum_rear_spkr_src[] = {
    341	"Main", "Second"};
    342static SOC_ENUM_SINGLE_DECL(soc_enum_rear_spkr_src,
    343	TDA7419_SECOND_SRC_REG, TDA7419_REAR_SPKR_SRC, enum_rear_spkr_src);
    344static const struct snd_kcontrol_new soc_mux_rear_spkr_src =
    345	SOC_DAPM_ENUM("Rear Speaker Source", soc_enum_rear_spkr_src);
    346static const char * const enum_sub_cut_off_freq[] = {
    347	"Flat", "80 Hz", "120 Hz", "160 Hz"};
    348static SOC_ENUM_SINGLE_DECL(soc_enum_sub_cut_off_freq,
    349	TDA7419_SUB_MID_BASS_REG, TDA7419_SUB_CUT_OFF_FREQ,
    350	enum_sub_cut_off_freq);
    351static const char * const enum_middle_center_freq[] = {
    352	"500 Hz", "1000 Hz", "1500 Hz", "2500 Hz"};
    353static SOC_ENUM_SINGLE_DECL(soc_enum_middle_center_freq,
    354	TDA7419_SUB_MID_BASS_REG, TDA7419_MIDDLE_CENTER_FREQ,
    355	enum_middle_center_freq);
    356static const char * const enum_bass_center_freq[] = {
    357	"60 Hz", "80 Hz", "100 Hz", "200 Hz"};
    358static SOC_ENUM_SINGLE_DECL(soc_enum_bass_center_freq,
    359	TDA7419_SUB_MID_BASS_REG, TDA7419_BASS_CENTER_FREQ,
    360	enum_bass_center_freq);
    361static const char * const enum_sa_q_factor[] = {
    362	"3.5", "1.75" };
    363static SOC_ENUM_SINGLE_DECL(soc_enum_sa_q_factor,
    364	TDA7419_SA_CLK_AC_REG, TDA7419_SA_Q_FACTOR, enum_sa_q_factor);
    365static const char * const enum_reset_mode[] = {
    366	"IIC", "Auto" };
    367static SOC_ENUM_SINGLE_DECL(soc_enum_reset_mode,
    368	TDA7419_SA_CLK_AC_REG, TDA7419_RESET_MODE, enum_reset_mode);
    369static const char * const enum_sa_src[] = {
    370	"Bass", "In Gain" };
    371static SOC_ENUM_SINGLE_DECL(soc_enum_sa_src,
    372	TDA7419_SA_CLK_AC_REG, TDA7419_SA_SOURCE, enum_sa_src);
    373static const char * const enum_clk_src[] = {
    374	"Internal", "External" };
    375static SOC_ENUM_SINGLE_DECL(soc_enum_clk_src,
    376	TDA7419_SA_CLK_AC_REG, TDA7419_CLK_SOURCE, enum_clk_src);
    377static const char * const enum_coupling_mode[] = {
    378	"DC Coupling (without HPF)", "AC Coupling after In Gain",
    379	"DC Coupling (with HPF)", "AC Coupling after Bass" };
    380static SOC_ENUM_SINGLE_DECL(soc_enum_coupling_mode,
    381	TDA7419_SA_CLK_AC_REG, TDA7419_COUPLING_MODE, enum_coupling_mode);
    382
    383/* ASoC Controls */
    384static struct snd_kcontrol_new tda7419_controls[] = {
    385SOC_SINGLE_TLV("Main Source Capture Volume", TDA7419_MAIN_SRC_REG,
    386	       TDA7419_MAIN_SRC_GAIN, 15, 0, tlv_src_gain),
    387SOC_SINGLE("Main Source AutoZero Switch", TDA7419_MAIN_SRC_REG,
    388	   TDA7419_MAIN_SRC_AUTOZERO, 1, 1),
    389SOC_SINGLE_TLV("Loudness Playback Volume", TDA7419_LOUDNESS_REG,
    390	       TDA7419_LOUDNESS_ATTEN, 15, 1, tlv_loudness_atten),
    391SOC_ENUM("Loudness Center Frequency", soc_enum_loudness_center_freq),
    392SOC_SINGLE("Loudness High Boost Switch", TDA7419_LOUDNESS_REG,
    393	   TDA7419_LOUDNESS_BOOST, 1, 1),
    394SOC_SINGLE("Loudness Soft Step Switch", TDA7419_LOUDNESS_REG,
    395	   TDA7419_LOUDNESS_SOFT_STEP, 1, 1),
    396SOC_SINGLE("Soft Mute Switch", TDA7419_MUTE_CLK_REG, TDA7419_SOFT_MUTE, 1, 1),
    397SOC_ENUM("Mute Influence", soc_enum_mute_influence),
    398SOC_ENUM("Soft Mute Time", soc_enum_soft_mute_time),
    399SOC_ENUM("Soft Step Time", soc_enum_soft_step_time),
    400SOC_SINGLE("Clock Fast Mode Switch", TDA7419_MUTE_CLK_REG,
    401	   TDA7419_CLK_FAST_MODE, 1, 1),
    402TDA7419_SINGLE_TLV("Master Playback Volume", TDA7419_VOLUME_REG,
    403		   0x7f, -80, 15, 0x10, 0, tlv_volume),
    404SOC_SINGLE("Volume Soft Step Switch", TDA7419_VOLUME_REG,
    405	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    406TDA7419_SINGLE_TLV("Treble Playback Volume", TDA7419_TREBLE_REG,
    407		   0x1f, -15, 15, 0x10, 1, tlv_filter),
    408SOC_ENUM("Treble Center Frequency", soc_enum_treble_center_freq),
    409SOC_ENUM("Reference Output Select", soc_enum_ref_out_select),
    410TDA7419_SINGLE_TLV("Middle Playback Volume", TDA7419_MIDDLE_REG,
    411		   0x1f, -15, 15, 0x10, 1, tlv_filter),
    412SOC_ENUM("Middle Q Factor", soc_enum_middle_q_factor),
    413SOC_SINGLE("Middle Soft Step Switch", TDA7419_MIDDLE_REG,
    414	   TDA7419_MIDDLE_SOFT_STEP, 1, 1),
    415TDA7419_SINGLE_TLV("Bass Playback Volume", TDA7419_BASS_REG,
    416		   0x1f, -15, 15, 0x10, 1, tlv_filter),
    417SOC_ENUM("Bass Q Factor", soc_enum_bass_q_factor),
    418SOC_SINGLE("Bass Soft Step Switch", TDA7419_BASS_REG,
    419	   TDA7419_BASS_SOFT_STEP, 1, 1),
    420SOC_SINGLE_TLV("Second Source Capture Volume", TDA7419_SECOND_SRC_REG,
    421	       TDA7419_SECOND_SRC_GAIN, 15, 0, tlv_src_gain),
    422SOC_ENUM("Subwoofer Cut-off Frequency", soc_enum_sub_cut_off_freq),
    423SOC_ENUM("Middle Center Frequency", soc_enum_middle_center_freq),
    424SOC_ENUM("Bass Center Frequency", soc_enum_bass_center_freq),
    425SOC_SINGLE("Bass DC Mode Switch", TDA7419_SUB_MID_BASS_REG,
    426	   TDA7419_BASS_DC_MODE, 1, 1),
    427SOC_SINGLE("Smoothing Filter Switch", TDA7419_SUB_MID_BASS_REG,
    428	   TDA7419_SMOOTHING_FILTER, 1, 1),
    429TDA7419_DOUBLE_R_TLV("Front Speaker Playback Volume", TDA7419_ATTENUATOR_LF_REG,
    430		     TDA7419_ATTENUATOR_RF_REG, 0x7f, -80, 15, 0x10, 0,
    431		     tlv_volume),
    432SOC_SINGLE("Left Front Soft Step Switch", TDA7419_ATTENUATOR_LF_REG,
    433	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    434SOC_SINGLE("Right Front Soft Step Switch", TDA7419_ATTENUATOR_RF_REG,
    435	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    436TDA7419_DOUBLE_R_TLV("Rear Speaker Playback Volume", TDA7419_ATTENUATOR_LR_REG,
    437		     TDA7419_ATTENUATOR_RR_REG, 0x7f, -80, 15, 0x10, 0,
    438		     tlv_volume),
    439SOC_SINGLE("Left Rear Soft Step Switch", TDA7419_ATTENUATOR_LR_REG,
    440	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    441SOC_SINGLE("Right Rear Soft Step Switch", TDA7419_ATTENUATOR_RR_REG,
    442	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    443TDA7419_SINGLE_TLV("Mixing Capture Volume", TDA7419_MIXING_LEVEL_REG,
    444		   0x7f, -80, 15, 0x10, 0, tlv_volume),
    445SOC_SINGLE("Mixing Level Soft Step Switch", TDA7419_MIXING_LEVEL_REG,
    446	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    447TDA7419_SINGLE_TLV("Subwoofer Playback Volume", TDA7419_ATTENUATOR_SUB_REG,
    448		   0x7f, -80, 15, 0x10, 0, tlv_volume),
    449SOC_SINGLE("Subwoofer Soft Step Switch", TDA7419_ATTENUATOR_SUB_REG,
    450	   TDA7419_VOLUME_SOFT_STEP, 1, 1),
    451SOC_ENUM("Spectrum Analyzer Q Factor", soc_enum_sa_q_factor),
    452SOC_ENUM("Spectrum Analyzer Reset Mode", soc_enum_reset_mode),
    453SOC_ENUM("Spectrum Analyzer Source", soc_enum_sa_src),
    454SOC_SINGLE("Spectrum Analyzer Run Switch", TDA7419_SA_CLK_AC_REG,
    455	   TDA7419_SA_RUN, 1, 1),
    456SOC_SINGLE("Spectrum Analyzer Reset Switch", TDA7419_SA_CLK_AC_REG,
    457	   TDA7419_RESET, 1, 1),
    458SOC_ENUM("Clock Source", soc_enum_clk_src),
    459SOC_ENUM("Coupling Mode", soc_enum_coupling_mode),
    460};
    461
    462static const struct snd_kcontrol_new soc_mixer_lf_output_controls[] = {
    463	SOC_DAPM_SINGLE("Mix to LF Speaker Switch",
    464			TDA7419_MIXING_GAIN_REG,
    465			TDA7419_MIX_LF, 1, 1),
    466};
    467
    468static const struct snd_kcontrol_new soc_mixer_rf_output_controls[] = {
    469	SOC_DAPM_SINGLE("Mix to RF Speaker Switch",
    470			TDA7419_MIXING_GAIN_REG,
    471			TDA7419_MIX_RF, 1, 1),
    472};
    473
    474static const struct snd_kcontrol_new soc_mix_enable_switch_controls[] = {
    475	SOC_DAPM_SINGLE("Switch", TDA7419_MIXING_GAIN_REG,
    476			TDA7419_MIX_ENABLE, 1, 1),
    477};
    478
    479static const struct snd_kcontrol_new soc_sub_enable_switch_controls[] = {
    480	SOC_DAPM_SINGLE("Switch", TDA7419_MIXING_GAIN_REG,
    481			TDA7419_MIX_ENABLE, 1, 1),
    482};
    483
    484static const struct snd_soc_dapm_widget tda7419_dapm_widgets[] = {
    485	SND_SOC_DAPM_INPUT("SE3L"),
    486	SND_SOC_DAPM_INPUT("SE3R"),
    487	SND_SOC_DAPM_INPUT("SE2L"),
    488	SND_SOC_DAPM_INPUT("SE2R"),
    489	SND_SOC_DAPM_INPUT("SE1L"),
    490	SND_SOC_DAPM_INPUT("SE1R"),
    491	SND_SOC_DAPM_INPUT("DIFFL"),
    492	SND_SOC_DAPM_INPUT("DIFFR"),
    493	SND_SOC_DAPM_INPUT("MIX"),
    494
    495	SND_SOC_DAPM_MUX("Main Source Select", SND_SOC_NOPM,
    496			 0, 0, &soc_mux_main_src_sel),
    497	SND_SOC_DAPM_MUX("Second Source Select", SND_SOC_NOPM,
    498			 0, 0, &soc_mux_second_src_sel),
    499	SND_SOC_DAPM_MUX("Rear Speaker Source", SND_SOC_NOPM,
    500			 0, 0, &soc_mux_rear_spkr_src),
    501
    502	SND_SOC_DAPM_SWITCH("Mix Enable", SND_SOC_NOPM,
    503			0, 0, &soc_mix_enable_switch_controls[0]),
    504	SND_SOC_DAPM_MIXER_NAMED_CTL("LF Output Mixer", SND_SOC_NOPM,
    505			0, 0, &soc_mixer_lf_output_controls[0],
    506			ARRAY_SIZE(soc_mixer_lf_output_controls)),
    507	SND_SOC_DAPM_MIXER_NAMED_CTL("RF Output Mixer", SND_SOC_NOPM,
    508			0, 0, &soc_mixer_rf_output_controls[0],
    509			ARRAY_SIZE(soc_mixer_rf_output_controls)),
    510
    511	SND_SOC_DAPM_SWITCH("Subwoofer Enable",
    512			SND_SOC_NOPM, 0, 0,
    513			&soc_sub_enable_switch_controls[0]),
    514
    515	SND_SOC_DAPM_OUTPUT("OUTLF"),
    516	SND_SOC_DAPM_OUTPUT("OUTRF"),
    517	SND_SOC_DAPM_OUTPUT("OUTLR"),
    518	SND_SOC_DAPM_OUTPUT("OUTRR"),
    519	SND_SOC_DAPM_OUTPUT("OUTSW"),
    520};
    521
    522static const struct snd_soc_dapm_route tda7419_dapm_routes[] = {
    523	{"Main Source Select", "SE3", "SE3L"},
    524	{"Main Source Select", "SE3", "SE3R"},
    525	{"Main Source Select", "SE2", "SE2L"},
    526	{"Main Source Select", "SE2", "SE2R"},
    527	{"Main Source Select", "SE1", "SE1L"},
    528	{"Main Source Select", "SE1", "SE1R"},
    529	{"Main Source Select", "SE", "DIFFL"},
    530	{"Main Source Select", "SE", "DIFFR"},
    531	{"Main Source Select", "QD", "DIFFL"},
    532	{"Main Source Select", "QD", "DIFFR"},
    533
    534	{"Second Source Select", "SE3", "SE3L"},
    535	{"Second Source Select", "SE3", "SE3R"},
    536	{"Second Source Select", "SE2", "SE2L"},
    537	{"Second Source Select", "SE2", "SE2R"},
    538	{"Second Source Select", "SE1", "SE1L"},
    539	{"Second Source Select", "SE1", "SE1R"},
    540	{"Second Source Select", "SE", "DIFFL"},
    541	{"Second Source Select", "SE", "DIFFR"},
    542	{"Second Source Select", "QD", "DIFFL"},
    543	{"Second Source Select", "QD", "DIFFR"},
    544
    545	{"Rear Speaker Source", "Main", "Main Source Select"},
    546	{"Rear Speaker Source", "Second", "Second Source Select"},
    547
    548	{"Subwoofer Enable", "Switch", "Main Source Select"},
    549
    550	{"Mix Enable", "Switch", "MIX"},
    551
    552	{"LF Output Mixer", NULL, "Main Source Select"},
    553	{"LF Output Mixer", "Mix to LF Speaker Switch", "Mix Enable"},
    554	{"RF Output Mixer", NULL, "Main Source Select"},
    555	{"RF Output Mixer", "Mix to RF Speaker Switch", "Mix Enable"},
    556
    557	{"OUTLF", NULL, "LF Output Mixer"},
    558	{"OUTRF", NULL, "RF Output Mixer"},
    559	{"OUTLR", NULL, "Rear Speaker Source"},
    560	{"OUTRR", NULL, "Rear Speaker Source"},
    561	{"OUTSW", NULL, "Subwoofer Enable"},
    562};
    563
    564static const struct snd_soc_component_driver tda7419_component_driver = {
    565	.name			= "tda7419",
    566	.controls		= tda7419_controls,
    567	.num_controls		= ARRAY_SIZE(tda7419_controls),
    568	.dapm_widgets		= tda7419_dapm_widgets,
    569	.num_dapm_widgets	= ARRAY_SIZE(tda7419_dapm_widgets),
    570	.dapm_routes		= tda7419_dapm_routes,
    571	.num_dapm_routes	= ARRAY_SIZE(tda7419_dapm_routes),
    572};
    573
    574static int tda7419_probe(struct i2c_client *i2c)
    575{
    576	struct tda7419_data *tda7419;
    577	int i, ret;
    578
    579	tda7419 = devm_kzalloc(&i2c->dev,
    580			       sizeof(struct tda7419_data),
    581			       GFP_KERNEL);
    582	if (tda7419 == NULL)
    583		return -ENOMEM;
    584
    585	i2c_set_clientdata(i2c, tda7419);
    586
    587	tda7419->regmap = devm_regmap_init_i2c(i2c, &tda7419_regmap_config);
    588	if (IS_ERR(tda7419->regmap)) {
    589		ret = PTR_ERR(tda7419->regmap);
    590		dev_err(&i2c->dev, "error initializing regmap: %d\n",
    591				ret);
    592		return ret;
    593	}
    594
    595	/*
    596	 * Reset registers to power-on defaults. The part does not provide a
    597	 * soft-reset function and the registers are not readable. This ensures
    598	 * that the cache matches register contents even if the registers have
    599	 * been previously initialized and not power cycled before probe.
    600	 */
    601	for (i = 0; i < ARRAY_SIZE(tda7419_regmap_defaults); i++)
    602		regmap_write(tda7419->regmap,
    603			     tda7419_regmap_defaults[i].reg,
    604			     tda7419_regmap_defaults[i].def);
    605
    606	ret = devm_snd_soc_register_component(&i2c->dev,
    607		&tda7419_component_driver, NULL, 0);
    608	if (ret < 0) {
    609		dev_err(&i2c->dev, "error registering component: %d\n",
    610				ret);
    611	}
    612
    613	return ret;
    614}
    615
    616static const struct i2c_device_id tda7419_i2c_id[] = {
    617	{ "tda7419", 0 },
    618	{ }
    619};
    620MODULE_DEVICE_TABLE(i2c, tda7419_i2c_id);
    621
    622static const struct of_device_id tda7419_of_match[] = {
    623	{ .compatible = "st,tda7419" },
    624	{ },
    625};
    626
    627static struct i2c_driver tda7419_driver = {
    628	.driver = {
    629		.name   = "tda7419",
    630		.of_match_table = tda7419_of_match,
    631	},
    632	.probe_new      = tda7419_probe,
    633	.id_table       = tda7419_i2c_id,
    634};
    635
    636module_i2c_driver(tda7419_driver);
    637
    638MODULE_AUTHOR("Matt Porter <mporter@konsulko.com>");
    639MODULE_DESCRIPTION("TDA7419 audio processor driver");
    640MODULE_LICENSE("GPL");