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

tas2770.c (19630B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D
      4// Audio Amplifier with Speaker I/V Sense
      5//
      6// Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/
      7//	Author: Tracy Yi <tracy-yi@ti.com>
      8//	Frank Shi <shifu0704@thundersoft.com>
      9
     10#include <linux/module.h>
     11#include <linux/moduleparam.h>
     12#include <linux/err.h>
     13#include <linux/init.h>
     14#include <linux/delay.h>
     15#include <linux/pm.h>
     16#include <linux/i2c.h>
     17#include <linux/gpio.h>
     18#include <linux/gpio/consumer.h>
     19#include <linux/regulator/consumer.h>
     20#include <linux/firmware.h>
     21#include <linux/regmap.h>
     22#include <linux/of.h>
     23#include <linux/of_gpio.h>
     24#include <linux/slab.h>
     25#include <sound/soc.h>
     26#include <sound/pcm.h>
     27#include <sound/pcm_params.h>
     28#include <sound/initval.h>
     29#include <sound/tlv.h>
     30
     31#include "tas2770.h"
     32
     33#define TAS2770_MDELAY 0xFFFFFFFE
     34
     35static void tas2770_reset(struct tas2770_priv *tas2770)
     36{
     37	if (tas2770->reset_gpio) {
     38		gpiod_set_value_cansleep(tas2770->reset_gpio, 0);
     39		msleep(20);
     40		gpiod_set_value_cansleep(tas2770->reset_gpio, 1);
     41		usleep_range(1000, 2000);
     42	}
     43
     44	snd_soc_component_write(tas2770->component, TAS2770_SW_RST,
     45		TAS2770_RST);
     46	usleep_range(1000, 2000);
     47}
     48
     49static int tas2770_set_bias_level(struct snd_soc_component *component,
     50				 enum snd_soc_bias_level level)
     51{
     52	struct tas2770_priv *tas2770 =
     53			snd_soc_component_get_drvdata(component);
     54
     55	switch (level) {
     56	case SND_SOC_BIAS_ON:
     57		snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
     58					      TAS2770_PWR_CTRL_MASK,
     59					      TAS2770_PWR_CTRL_ACTIVE);
     60		break;
     61	case SND_SOC_BIAS_STANDBY:
     62	case SND_SOC_BIAS_PREPARE:
     63		snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
     64					      TAS2770_PWR_CTRL_MASK,
     65					      TAS2770_PWR_CTRL_MUTE);
     66		break;
     67	case SND_SOC_BIAS_OFF:
     68		snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
     69					      TAS2770_PWR_CTRL_MASK,
     70					      TAS2770_PWR_CTRL_SHUTDOWN);
     71		break;
     72
     73	default:
     74		dev_err(tas2770->dev, "wrong power level setting %d\n", level);
     75		return -EINVAL;
     76	}
     77
     78	return 0;
     79}
     80
     81#ifdef CONFIG_PM
     82static int tas2770_codec_suspend(struct snd_soc_component *component)
     83{
     84	struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
     85	int ret = 0;
     86
     87	regcache_cache_only(tas2770->regmap, true);
     88	regcache_mark_dirty(tas2770->regmap);
     89
     90	if (tas2770->sdz_gpio) {
     91		gpiod_set_value_cansleep(tas2770->sdz_gpio, 0);
     92	} else {
     93		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
     94						    TAS2770_PWR_CTRL_MASK,
     95						    TAS2770_PWR_CTRL_SHUTDOWN);
     96		if (ret < 0) {
     97			regcache_cache_only(tas2770->regmap, false);
     98			regcache_sync(tas2770->regmap);
     99			return ret;
    100		}
    101
    102		ret = 0;
    103	}
    104
    105	return ret;
    106}
    107
    108static int tas2770_codec_resume(struct snd_soc_component *component)
    109{
    110	struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
    111	int ret;
    112
    113	if (tas2770->sdz_gpio) {
    114		gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
    115		usleep_range(1000, 2000);
    116	} else {
    117		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
    118						    TAS2770_PWR_CTRL_MASK,
    119						    TAS2770_PWR_CTRL_ACTIVE);
    120		if (ret < 0)
    121			return ret;
    122	}
    123
    124	regcache_cache_only(tas2770->regmap, false);
    125
    126	return regcache_sync(tas2770->regmap);
    127}
    128#else
    129#define tas2770_codec_suspend NULL
    130#define tas2770_codec_resume NULL
    131#endif
    132
    133static const char * const tas2770_ASI1_src[] = {
    134	"I2C offset", "Left", "Right", "LeftRightDiv2",
    135};
    136
    137static SOC_ENUM_SINGLE_DECL(
    138	tas2770_ASI1_src_enum, TAS2770_TDM_CFG_REG2,
    139	4, tas2770_ASI1_src);
    140
    141static const struct snd_kcontrol_new tas2770_asi1_mux =
    142	SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
    143
    144static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
    145			     struct snd_kcontrol *kcontrol, int event)
    146{
    147	struct snd_soc_component *component =
    148			snd_soc_dapm_to_component(w->dapm);
    149	struct tas2770_priv *tas2770 =
    150			snd_soc_component_get_drvdata(component);
    151	int ret;
    152
    153	switch (event) {
    154	case SND_SOC_DAPM_POST_PMU:
    155		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
    156						    TAS2770_PWR_CTRL_MASK,
    157						    TAS2770_PWR_CTRL_MUTE);
    158		break;
    159	case SND_SOC_DAPM_PRE_PMD:
    160		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
    161						    TAS2770_PWR_CTRL_MASK,
    162						    TAS2770_PWR_CTRL_SHUTDOWN);
    163		break;
    164	default:
    165		dev_err(tas2770->dev, "Not supported evevt\n");
    166		return -EINVAL;
    167	}
    168
    169	if (ret < 0)
    170		return ret;
    171
    172	return 0;
    173}
    174
    175static const struct snd_kcontrol_new isense_switch =
    176	SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 3, 1, 1);
    177static const struct snd_kcontrol_new vsense_switch =
    178	SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1);
    179
    180static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
    181	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
    182	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2770_asi1_mux),
    183	SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch),
    184	SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch),
    185	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
    186			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
    187	SND_SOC_DAPM_OUTPUT("OUT"),
    188	SND_SOC_DAPM_SIGGEN("VMON"),
    189	SND_SOC_DAPM_SIGGEN("IMON")
    190};
    191
    192static const struct snd_soc_dapm_route tas2770_audio_map[] = {
    193	{"ASI1 Sel", "I2C offset", "ASI1"},
    194	{"ASI1 Sel", "Left", "ASI1"},
    195	{"ASI1 Sel", "Right", "ASI1"},
    196	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
    197	{"DAC", NULL, "ASI1 Sel"},
    198	{"OUT", NULL, "DAC"},
    199	{"ISENSE", "Switch", "IMON"},
    200	{"VSENSE", "Switch", "VMON"},
    201};
    202
    203static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction)
    204{
    205	struct snd_soc_component *component = dai->component;
    206	int ret;
    207
    208	if (mute)
    209		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
    210						    TAS2770_PWR_CTRL_MASK,
    211						    TAS2770_PWR_CTRL_MUTE);
    212	else
    213		ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
    214						    TAS2770_PWR_CTRL_MASK,
    215						    TAS2770_PWR_CTRL_ACTIVE);
    216
    217	if (ret < 0)
    218		return ret;
    219
    220	return 0;
    221}
    222
    223static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth)
    224{
    225	int ret;
    226	struct snd_soc_component *component = tas2770->component;
    227
    228	switch (bitwidth) {
    229	case SNDRV_PCM_FORMAT_S16_LE:
    230		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    231						    TAS2770_TDM_CFG_REG2_RXW_MASK,
    232						    TAS2770_TDM_CFG_REG2_RXW_16BITS);
    233		tas2770->v_sense_slot = tas2770->i_sense_slot + 2;
    234		break;
    235	case SNDRV_PCM_FORMAT_S24_LE:
    236		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    237						    TAS2770_TDM_CFG_REG2_RXW_MASK,
    238						    TAS2770_TDM_CFG_REG2_RXW_24BITS);
    239		tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
    240		break;
    241	case SNDRV_PCM_FORMAT_S32_LE:
    242		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    243						    TAS2770_TDM_CFG_REG2_RXW_MASK,
    244						    TAS2770_TDM_CFG_REG2_RXW_32BITS);
    245		tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
    246		break;
    247
    248	default:
    249		return -EINVAL;
    250	}
    251
    252	if (ret < 0)
    253		return ret;
    254
    255	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5,
    256					    TAS2770_TDM_CFG_REG5_VSNS_MASK |
    257					    TAS2770_TDM_CFG_REG5_50_MASK,
    258					    TAS2770_TDM_CFG_REG5_VSNS_ENABLE |
    259		tas2770->v_sense_slot);
    260	if (ret < 0)
    261		return ret;
    262
    263	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6,
    264					    TAS2770_TDM_CFG_REG6_ISNS_MASK |
    265					    TAS2770_TDM_CFG_REG6_50_MASK,
    266					    TAS2770_TDM_CFG_REG6_ISNS_ENABLE |
    267					    tas2770->i_sense_slot);
    268	if (ret < 0)
    269		return ret;
    270
    271	return 0;
    272}
    273
    274static int tas2770_set_samplerate(struct tas2770_priv *tas2770, int samplerate)
    275{
    276	struct snd_soc_component *component = tas2770->component;
    277	int ramp_rate_val;
    278	int ret;
    279
    280	switch (samplerate) {
    281	case 48000:
    282		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
    283				TAS2770_TDM_CFG_REG0_31_44_1_48KHZ;
    284		break;
    285	case 44100:
    286		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
    287				TAS2770_TDM_CFG_REG0_31_44_1_48KHZ;
    288		break;
    289	case 96000:
    290		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
    291				TAS2770_TDM_CFG_REG0_31_88_2_96KHZ;
    292		break;
    293	case 88200:
    294		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
    295				TAS2770_TDM_CFG_REG0_31_88_2_96KHZ;
    296		break;
    297	case 192000:
    298		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
    299				TAS2770_TDM_CFG_REG0_31_176_4_192KHZ;
    300		break;
    301	case 176400:
    302		ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
    303				TAS2770_TDM_CFG_REG0_31_176_4_192KHZ;
    304		break;
    305	default:
    306		return -EINVAL;
    307	}
    308
    309	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG0,
    310					    TAS2770_TDM_CFG_REG0_SMP_MASK |
    311					    TAS2770_TDM_CFG_REG0_31_MASK,
    312					    ramp_rate_val);
    313	if (ret < 0)
    314		return ret;
    315
    316	return 0;
    317}
    318
    319static int tas2770_hw_params(struct snd_pcm_substream *substream,
    320			     struct snd_pcm_hw_params *params,
    321			     struct snd_soc_dai *dai)
    322{
    323	struct snd_soc_component *component = dai->component;
    324	struct tas2770_priv *tas2770 =
    325			snd_soc_component_get_drvdata(component);
    326	int ret;
    327
    328	ret = tas2770_set_bitwidth(tas2770, params_format(params));
    329	if (ret)
    330		return ret;
    331
    332	return tas2770_set_samplerate(tas2770, params_rate(params));
    333}
    334
    335static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
    336{
    337	struct snd_soc_component *component = dai->component;
    338	struct tas2770_priv *tas2770 =
    339			snd_soc_component_get_drvdata(component);
    340	u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
    341	int ret;
    342
    343	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    344	case SND_SOC_DAIFMT_CBS_CFS:
    345		break;
    346	default:
    347		dev_err(tas2770->dev, "ASI format master is not found\n");
    348		return -EINVAL;
    349	}
    350
    351	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    352	case SND_SOC_DAIFMT_NB_NF:
    353		asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING;
    354		break;
    355	case SND_SOC_DAIFMT_IB_NF:
    356		asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_FALING;
    357		break;
    358	default:
    359		dev_err(tas2770->dev, "ASI format Inverse is not found\n");
    360		return -EINVAL;
    361	}
    362
    363	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
    364					    TAS2770_TDM_CFG_REG1_RX_MASK,
    365					    asi_cfg_1);
    366	if (ret < 0)
    367		return ret;
    368
    369	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    370	case SND_SOC_DAIFMT_I2S:
    371		tdm_rx_start_slot = 1;
    372		break;
    373	case SND_SOC_DAIFMT_DSP_A:
    374		tdm_rx_start_slot = 0;
    375		break;
    376	case SND_SOC_DAIFMT_DSP_B:
    377		tdm_rx_start_slot = 1;
    378		break;
    379	case SND_SOC_DAIFMT_LEFT_J:
    380		tdm_rx_start_slot = 0;
    381		break;
    382	default:
    383		dev_err(tas2770->dev,
    384			"DAI Format is not found, fmt=0x%x\n", fmt);
    385		return -EINVAL;
    386	}
    387
    388	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
    389					    TAS2770_TDM_CFG_REG1_MASK,
    390					    (tdm_rx_start_slot << TAS2770_TDM_CFG_REG1_51_SHIFT));
    391	if (ret < 0)
    392		return ret;
    393
    394	return 0;
    395}
    396
    397static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
    398				unsigned int tx_mask,
    399				unsigned int rx_mask,
    400				int slots, int slot_width)
    401{
    402	struct snd_soc_component *component = dai->component;
    403	int left_slot, right_slot;
    404	int ret;
    405
    406	if (tx_mask == 0 || rx_mask != 0)
    407		return -EINVAL;
    408
    409	if (slots == 1) {
    410		if (tx_mask != 1)
    411			return -EINVAL;
    412
    413		left_slot = 0;
    414		right_slot = 0;
    415	} else {
    416		left_slot = __ffs(tx_mask);
    417		tx_mask &= ~(1 << left_slot);
    418		if (tx_mask == 0) {
    419			right_slot = left_slot;
    420		} else {
    421			right_slot = __ffs(tx_mask);
    422			tx_mask &= ~(1 << right_slot);
    423		}
    424	}
    425
    426	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
    427		return -EINVAL;
    428
    429	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
    430					    TAS2770_TDM_CFG_REG3_30_MASK,
    431					    (left_slot << TAS2770_TDM_CFG_REG3_30_SHIFT));
    432	if (ret < 0)
    433		return ret;
    434	ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
    435					    TAS2770_TDM_CFG_REG3_RXS_MASK,
    436					    (right_slot << TAS2770_TDM_CFG_REG3_RXS_SHIFT));
    437	if (ret < 0)
    438		return ret;
    439
    440	switch (slot_width) {
    441	case 16:
    442		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    443						    TAS2770_TDM_CFG_REG2_RXS_MASK,
    444						    TAS2770_TDM_CFG_REG2_RXS_16BITS);
    445		break;
    446	case 24:
    447		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    448						    TAS2770_TDM_CFG_REG2_RXS_MASK,
    449						    TAS2770_TDM_CFG_REG2_RXS_24BITS);
    450		break;
    451	case 32:
    452		ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
    453						    TAS2770_TDM_CFG_REG2_RXS_MASK,
    454						    TAS2770_TDM_CFG_REG2_RXS_32BITS);
    455		break;
    456	case 0:
    457		/* Do not change slot width */
    458		ret = 0;
    459		break;
    460	default:
    461		ret = -EINVAL;
    462	}
    463
    464	if (ret < 0)
    465		return ret;
    466
    467	return 0;
    468}
    469
    470static const struct snd_soc_dai_ops tas2770_dai_ops = {
    471	.mute_stream = tas2770_mute,
    472	.hw_params  = tas2770_hw_params,
    473	.set_fmt    = tas2770_set_fmt,
    474	.set_tdm_slot = tas2770_set_dai_tdm_slot,
    475	.no_capture_mute = 1,
    476};
    477
    478#define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
    479		SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
    480
    481#define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
    482					   SNDRV_PCM_RATE_96000 |\
    483					    SNDRV_PCM_RATE_192000\
    484					  )
    485
    486static struct snd_soc_dai_driver tas2770_dai_driver[] = {
    487	{
    488		.name = "tas2770 ASI1",
    489		.id = 0,
    490		.playback = {
    491			.stream_name    = "ASI1 Playback",
    492			.channels_min   = 2,
    493			.channels_max   = 2,
    494			.rates      = TAS2770_RATES,
    495			.formats    = TAS2770_FORMATS,
    496		},
    497		.capture = {
    498			.stream_name    = "ASI1 Capture",
    499			.channels_min   = 0,
    500			.channels_max   = 2,
    501			.rates          = TAS2770_RATES,
    502			.formats    = TAS2770_FORMATS,
    503		},
    504		.ops = &tas2770_dai_ops,
    505		.symmetric_rate = 1,
    506	},
    507};
    508
    509static int tas2770_codec_probe(struct snd_soc_component *component)
    510{
    511	struct tas2770_priv *tas2770 =
    512			snd_soc_component_get_drvdata(component);
    513
    514	tas2770->component = component;
    515
    516	if (tas2770->sdz_gpio) {
    517		gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
    518		usleep_range(1000, 2000);
    519	}
    520
    521	tas2770_reset(tas2770);
    522
    523	return 0;
    524}
    525
    526static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
    527static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
    528
    529static const struct snd_kcontrol_new tas2770_snd_controls[] = {
    530	SOC_SINGLE_TLV("Speaker Playback Volume", TAS2770_PLAY_CFG_REG2,
    531		       0, TAS2770_PLAY_CFG_REG2_VMAX, 1, tas2770_playback_volume),
    532	SOC_SINGLE_TLV("Amp Gain Volume", TAS2770_PLAY_CFG_REG0, 0, 0x14, 0,
    533		       tas2770_digital_tlv),
    534};
    535
    536static const struct snd_soc_component_driver soc_component_driver_tas2770 = {
    537	.probe			= tas2770_codec_probe,
    538	.suspend		= tas2770_codec_suspend,
    539	.resume			= tas2770_codec_resume,
    540	.set_bias_level = tas2770_set_bias_level,
    541	.controls		= tas2770_snd_controls,
    542	.num_controls		= ARRAY_SIZE(tas2770_snd_controls),
    543	.dapm_widgets		= tas2770_dapm_widgets,
    544	.num_dapm_widgets	= ARRAY_SIZE(tas2770_dapm_widgets),
    545	.dapm_routes		= tas2770_audio_map,
    546	.num_dapm_routes	= ARRAY_SIZE(tas2770_audio_map),
    547	.idle_bias_on		= 1,
    548	.endianness		= 1,
    549	.non_legacy_dai_naming	= 1,
    550};
    551
    552static int tas2770_register_codec(struct tas2770_priv *tas2770)
    553{
    554	return devm_snd_soc_register_component(tas2770->dev,
    555		&soc_component_driver_tas2770,
    556		tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
    557}
    558
    559static const struct reg_default tas2770_reg_defaults[] = {
    560	{ TAS2770_PAGE, 0x00 },
    561	{ TAS2770_SW_RST, 0x00 },
    562	{ TAS2770_PWR_CTRL, 0x0e },
    563	{ TAS2770_PLAY_CFG_REG0, 0x10 },
    564	{ TAS2770_PLAY_CFG_REG1, 0x01 },
    565	{ TAS2770_PLAY_CFG_REG2, 0x00 },
    566	{ TAS2770_MSC_CFG_REG0, 0x07 },
    567	{ TAS2770_TDM_CFG_REG1, 0x02 },
    568	{ TAS2770_TDM_CFG_REG2, 0x0a },
    569	{ TAS2770_TDM_CFG_REG3, 0x10 },
    570	{ TAS2770_INT_MASK_REG0, 0xfc },
    571	{ TAS2770_INT_MASK_REG1, 0xb1 },
    572	{ TAS2770_INT_CFG, 0x05 },
    573	{ TAS2770_MISC_IRQ, 0x81 },
    574	{ TAS2770_CLK_CGF, 0x0c },
    575
    576};
    577
    578static bool tas2770_volatile(struct device *dev, unsigned int reg)
    579{
    580	switch (reg) {
    581	case TAS2770_PAGE: /* regmap implementation requires this */
    582	case TAS2770_SW_RST: /* always clears after write */
    583	case TAS2770_BO_PRV_REG0:/* has a self clearing bit */
    584	case TAS2770_LVE_INT_REG0:
    585	case TAS2770_LVE_INT_REG1:
    586	case TAS2770_LAT_INT_REG0:/* Sticky interrupt flags */
    587	case TAS2770_LAT_INT_REG1:/* Sticky interrupt flags */
    588	case TAS2770_VBAT_MSB:
    589	case TAS2770_VBAT_LSB:
    590	case TAS2770_TEMP_MSB:
    591	case TAS2770_TEMP_LSB:
    592		return true;
    593	}
    594
    595	return false;
    596}
    597
    598static bool tas2770_writeable(struct device *dev, unsigned int reg)
    599{
    600	switch (reg) {
    601	case TAS2770_LVE_INT_REG0:
    602	case TAS2770_LVE_INT_REG1:
    603	case TAS2770_LAT_INT_REG0:
    604	case TAS2770_LAT_INT_REG1:
    605	case TAS2770_VBAT_MSB:
    606	case TAS2770_VBAT_LSB:
    607	case TAS2770_TEMP_MSB:
    608	case TAS2770_TEMP_LSB:
    609	case TAS2770_TDM_CLK_DETC:
    610	case TAS2770_REV_AND_GPID:
    611		return false;
    612	}
    613
    614	return true;
    615}
    616
    617static const struct regmap_range_cfg tas2770_regmap_ranges[] = {
    618	{
    619		.range_min = 0,
    620		.range_max = 1 * 128,
    621		.selector_reg = TAS2770_PAGE,
    622		.selector_mask = 0xff,
    623		.selector_shift = 0,
    624		.window_start = 0,
    625		.window_len = 128,
    626	},
    627};
    628
    629static const struct regmap_config tas2770_i2c_regmap = {
    630	.reg_bits = 8,
    631	.val_bits = 8,
    632	.writeable_reg = tas2770_writeable,
    633	.volatile_reg = tas2770_volatile,
    634	.reg_defaults = tas2770_reg_defaults,
    635	.num_reg_defaults = ARRAY_SIZE(tas2770_reg_defaults),
    636	.cache_type = REGCACHE_RBTREE,
    637	.ranges = tas2770_regmap_ranges,
    638	.num_ranges = ARRAY_SIZE(tas2770_regmap_ranges),
    639	.max_register = 1 * 128,
    640};
    641
    642static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
    643{
    644	int rc = 0;
    645
    646	rc = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
    647				      &tas2770->i_sense_slot);
    648	if (rc) {
    649		dev_info(tas2770->dev, "Property %s is missing setting default slot\n",
    650			 "ti,imon-slot-no");
    651
    652		tas2770->i_sense_slot = 0;
    653	}
    654
    655	rc = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
    656				      &tas2770->v_sense_slot);
    657	if (rc) {
    658		dev_info(tas2770->dev, "Property %s is missing setting default slot\n",
    659			 "ti,vmon-slot-no");
    660
    661		tas2770->v_sense_slot = 2;
    662	}
    663
    664	tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
    665	if (IS_ERR(tas2770->sdz_gpio)) {
    666		if (PTR_ERR(tas2770->sdz_gpio) == -EPROBE_DEFER)
    667			return -EPROBE_DEFER;
    668
    669		tas2770->sdz_gpio = NULL;
    670	}
    671
    672	return 0;
    673}
    674
    675static int tas2770_i2c_probe(struct i2c_client *client)
    676{
    677	struct tas2770_priv *tas2770;
    678	int result;
    679
    680	tas2770 = devm_kzalloc(&client->dev, sizeof(struct tas2770_priv),
    681			       GFP_KERNEL);
    682	if (!tas2770)
    683		return -ENOMEM;
    684
    685	tas2770->dev = &client->dev;
    686	i2c_set_clientdata(client, tas2770);
    687	dev_set_drvdata(&client->dev, tas2770);
    688
    689	tas2770->regmap = devm_regmap_init_i2c(client, &tas2770_i2c_regmap);
    690	if (IS_ERR(tas2770->regmap)) {
    691		result = PTR_ERR(tas2770->regmap);
    692		dev_err(&client->dev, "Failed to allocate register map: %d\n",
    693			result);
    694		return result;
    695	}
    696
    697	if (client->dev.of_node) {
    698		result = tas2770_parse_dt(&client->dev, tas2770);
    699		if (result) {
    700			dev_err(tas2770->dev, "%s: Failed to parse devicetree\n",
    701				__func__);
    702			return result;
    703		}
    704	}
    705
    706	tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, "reset",
    707						      GPIOD_OUT_HIGH);
    708	if (IS_ERR(tas2770->reset_gpio)) {
    709		if (PTR_ERR(tas2770->reset_gpio) == -EPROBE_DEFER) {
    710			tas2770->reset_gpio = NULL;
    711			return -EPROBE_DEFER;
    712		}
    713	}
    714
    715	result = tas2770_register_codec(tas2770);
    716	if (result)
    717		dev_err(tas2770->dev, "Register codec failed.\n");
    718
    719	return result;
    720}
    721
    722static const struct i2c_device_id tas2770_i2c_id[] = {
    723	{ "tas2770", 0},
    724	{ }
    725};
    726MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id);
    727
    728#if defined(CONFIG_OF)
    729static const struct of_device_id tas2770_of_match[] = {
    730	{ .compatible = "ti,tas2770" },
    731	{},
    732};
    733MODULE_DEVICE_TABLE(of, tas2770_of_match);
    734#endif
    735
    736static struct i2c_driver tas2770_i2c_driver = {
    737	.driver = {
    738		.name   = "tas2770",
    739		.of_match_table = of_match_ptr(tas2770_of_match),
    740	},
    741	.probe_new  = tas2770_i2c_probe,
    742	.id_table   = tas2770_i2c_id,
    743};
    744module_i2c_driver(tas2770_i2c_driver);
    745
    746MODULE_AUTHOR("Shi Fu <shifu0704@thundersoft.com>");
    747MODULE_DESCRIPTION("TAS2770 I2C Smart Amplifier driver");
    748MODULE_LICENSE("GPL v2");