162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci /*
362306a36Sopenharmony_ci * Audio Codec driver supporting:
462306a36Sopenharmony_ci *  AD1835A, AD1836, AD1837A, AD1838A, AD1839A
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright 2009-2011 Analog Devices Inc.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/init.h>
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <sound/core.h>
1562306a36Sopenharmony_ci#include <sound/pcm.h>
1662306a36Sopenharmony_ci#include <sound/pcm_params.h>
1762306a36Sopenharmony_ci#include <sound/initval.h>
1862306a36Sopenharmony_ci#include <sound/soc.h>
1962306a36Sopenharmony_ci#include <sound/tlv.h>
2062306a36Sopenharmony_ci#include <linux/spi/spi.h>
2162306a36Sopenharmony_ci#include <linux/regmap.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include "ad1836.h"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cienum ad1836_type {
2662306a36Sopenharmony_ci	AD1835,
2762306a36Sopenharmony_ci	AD1836,
2862306a36Sopenharmony_ci	AD1838,
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/* codec private data */
3262306a36Sopenharmony_cistruct ad1836_priv {
3362306a36Sopenharmony_ci	enum ad1836_type type;
3462306a36Sopenharmony_ci	struct regmap *regmap;
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * AD1836 volume/mute/de-emphasis etc. controls
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_cistatic const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,
4362306a36Sopenharmony_ci			    AD1836_DAC_CTRL1, 8, ad1836_deemp);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define AD1836_DAC_VOLUME(x) \
4662306a36Sopenharmony_ci	SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
4762306a36Sopenharmony_ci			AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define AD1836_DAC_SWITCH(x) \
5062306a36Sopenharmony_ci	SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \
5162306a36Sopenharmony_ci			AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define AD1836_ADC_SWITCH(x) \
5462306a36Sopenharmony_ci	SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \
5562306a36Sopenharmony_ci		AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad183x_dac_controls[] = {
5862306a36Sopenharmony_ci	AD1836_DAC_VOLUME(1),
5962306a36Sopenharmony_ci	AD1836_DAC_SWITCH(1),
6062306a36Sopenharmony_ci	AD1836_DAC_VOLUME(2),
6162306a36Sopenharmony_ci	AD1836_DAC_SWITCH(2),
6262306a36Sopenharmony_ci	AD1836_DAC_VOLUME(3),
6362306a36Sopenharmony_ci	AD1836_DAC_SWITCH(3),
6462306a36Sopenharmony_ci	AD1836_DAC_VOLUME(4),
6562306a36Sopenharmony_ci	AD1836_DAC_SWITCH(4),
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {
6962306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DAC1OUT"),
7062306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DAC2OUT"),
7162306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DAC3OUT"),
7262306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DAC4OUT"),
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route ad183x_dac_routes[] = {
7662306a36Sopenharmony_ci	{ "DAC1OUT", NULL, "DAC" },
7762306a36Sopenharmony_ci	{ "DAC2OUT", NULL, "DAC" },
7862306a36Sopenharmony_ci	{ "DAC3OUT", NULL, "DAC" },
7962306a36Sopenharmony_ci	{ "DAC4OUT", NULL, "DAC" },
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad183x_adc_controls[] = {
8362306a36Sopenharmony_ci	AD1836_ADC_SWITCH(1),
8462306a36Sopenharmony_ci	AD1836_ADC_SWITCH(2),
8562306a36Sopenharmony_ci	AD1836_ADC_SWITCH(3),
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {
8962306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("ADC1IN"),
9062306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("ADC2IN"),
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route ad183x_adc_routes[] = {
9462306a36Sopenharmony_ci	{ "ADC", NULL, "ADC1IN" },
9562306a36Sopenharmony_ci	{ "ADC", NULL, "ADC2IN" },
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad183x_controls[] = {
9962306a36Sopenharmony_ci	/* ADC high-pass filter */
10062306a36Sopenharmony_ci	SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
10162306a36Sopenharmony_ci			AD1836_ADC_HIGHPASS_FILTER, 1, 0),
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* DAC de-emphasis */
10462306a36Sopenharmony_ci	SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {
10862306a36Sopenharmony_ci	SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
10962306a36Sopenharmony_ci				AD1836_DAC_POWERDOWN, 1),
11062306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
11162306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
11262306a36Sopenharmony_ci				AD1836_ADC_POWERDOWN, 1, NULL, 0),
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route ad183x_dapm_routes[] = {
11662306a36Sopenharmony_ci	{ "DAC", NULL, "ADC_PWR" },
11762306a36Sopenharmony_ci	{ "ADC", NULL, "ADC_PWR" },
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic const struct snd_kcontrol_new ad1836_controls[] = {
12362306a36Sopenharmony_ci	SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,
12462306a36Sopenharmony_ci	    ad1836_in_tlv),
12562306a36Sopenharmony_ci};
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/*
12862306a36Sopenharmony_ci * DAI ops entries
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,
13262306a36Sopenharmony_ci		unsigned int fmt)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
13562306a36Sopenharmony_ci	/* at present, we support adc aux mode to interface with
13662306a36Sopenharmony_ci	 * blackfin sport tdm mode
13762306a36Sopenharmony_ci	 */
13862306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
13962306a36Sopenharmony_ci		break;
14062306a36Sopenharmony_ci	default:
14162306a36Sopenharmony_ci		return -EINVAL;
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
14562306a36Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
14662306a36Sopenharmony_ci		break;
14762306a36Sopenharmony_ci	default:
14862306a36Sopenharmony_ci		return -EINVAL;
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
15262306a36Sopenharmony_ci	/* ALCLK,ABCLK are both output, AD1836 can only be provider */
15362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBP_CFP:
15462306a36Sopenharmony_ci		break;
15562306a36Sopenharmony_ci	default:
15662306a36Sopenharmony_ci		return -EINVAL;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	return 0;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic int ad1836_hw_params(struct snd_pcm_substream *substream,
16362306a36Sopenharmony_ci		struct snd_pcm_hw_params *params,
16462306a36Sopenharmony_ci		struct snd_soc_dai *dai)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(dai->component);
16762306a36Sopenharmony_ci	int word_len = 0;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	/* bit size */
17062306a36Sopenharmony_ci	switch (params_width(params)) {
17162306a36Sopenharmony_ci	case 16:
17262306a36Sopenharmony_ci		word_len = AD1836_WORD_LEN_16;
17362306a36Sopenharmony_ci		break;
17462306a36Sopenharmony_ci	case 20:
17562306a36Sopenharmony_ci		word_len = AD1836_WORD_LEN_20;
17662306a36Sopenharmony_ci		break;
17762306a36Sopenharmony_ci	case 24:
17862306a36Sopenharmony_ci	case 32:
17962306a36Sopenharmony_ci		word_len = AD1836_WORD_LEN_24;
18062306a36Sopenharmony_ci		break;
18162306a36Sopenharmony_ci	default:
18262306a36Sopenharmony_ci		return -EINVAL;
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,
18662306a36Sopenharmony_ci		AD1836_DAC_WORD_LEN_MASK,
18762306a36Sopenharmony_ci		word_len << AD1836_DAC_WORD_LEN_OFFSET);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
19062306a36Sopenharmony_ci		AD1836_ADC_WORD_LEN_MASK,
19162306a36Sopenharmony_ci		word_len << AD1836_ADC_WORD_OFFSET);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	return 0;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic const struct snd_soc_dai_ops ad1836_dai_ops = {
19762306a36Sopenharmony_ci	.hw_params = ad1836_hw_params,
19862306a36Sopenharmony_ci	.set_fmt = ad1836_set_dai_fmt,
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#define AD183X_DAI(_name, num_dacs, num_adcs) \
20262306a36Sopenharmony_ci{ \
20362306a36Sopenharmony_ci	.name = _name "-hifi", \
20462306a36Sopenharmony_ci	.playback = { \
20562306a36Sopenharmony_ci		.stream_name = "Playback", \
20662306a36Sopenharmony_ci		.channels_min = 2, \
20762306a36Sopenharmony_ci		.channels_max = (num_dacs) * 2, \
20862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,  \
20962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
21062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
21162306a36Sopenharmony_ci	}, \
21262306a36Sopenharmony_ci	.capture = { \
21362306a36Sopenharmony_ci		.stream_name = "Capture", \
21462306a36Sopenharmony_ci		.channels_min = 2, \
21562306a36Sopenharmony_ci		.channels_max = (num_adcs) * 2, \
21662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000, \
21762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
21862306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
21962306a36Sopenharmony_ci	}, \
22062306a36Sopenharmony_ci	.ops = &ad1836_dai_ops, \
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic struct snd_soc_dai_driver ad183x_dais[] = {
22462306a36Sopenharmony_ci	[AD1835] = AD183X_DAI("ad1835", 4, 1),
22562306a36Sopenharmony_ci	[AD1836] = AD183X_DAI("ad1836", 3, 2),
22662306a36Sopenharmony_ci	[AD1838] = AD183X_DAI("ad1838", 3, 1),
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci#ifdef CONFIG_PM
23062306a36Sopenharmony_cistatic int ad1836_suspend(struct snd_soc_component *component)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
23362306a36Sopenharmony_ci	/* reset clock control mode */
23462306a36Sopenharmony_ci	return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
23562306a36Sopenharmony_ci		AD1836_ADC_SERFMT_MASK, 0);
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic int ad1836_resume(struct snd_soc_component *component)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
24162306a36Sopenharmony_ci	/* restore clock control mode */
24262306a36Sopenharmony_ci	return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
24362306a36Sopenharmony_ci		AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci#else
24662306a36Sopenharmony_ci#define ad1836_suspend NULL
24762306a36Sopenharmony_ci#define ad1836_resume  NULL
24862306a36Sopenharmony_ci#endif
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic int ad1836_probe(struct snd_soc_component *component)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
25362306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
25462306a36Sopenharmony_ci	int num_dacs, num_adcs;
25562306a36Sopenharmony_ci	int ret = 0;
25662306a36Sopenharmony_ci	int i;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;
25962306a36Sopenharmony_ci	num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	/* default setting for ad1836 */
26262306a36Sopenharmony_ci	/* de-emphasis: 48kHz, power-on dac */
26362306a36Sopenharmony_ci	regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300);
26462306a36Sopenharmony_ci	/* unmute dac channels */
26562306a36Sopenharmony_ci	regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0);
26662306a36Sopenharmony_ci	/* high-pass filter enable, power-on adc */
26762306a36Sopenharmony_ci	regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100);
26862306a36Sopenharmony_ci	/* unmute adc channles, adc aux mode */
26962306a36Sopenharmony_ci	regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180);
27062306a36Sopenharmony_ci	/* volume */
27162306a36Sopenharmony_ci	for (i = 1; i <= num_dacs; ++i) {
27262306a36Sopenharmony_ci		regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF);
27362306a36Sopenharmony_ci		regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF);
27462306a36Sopenharmony_ci	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (ad1836->type == AD1836) {
27762306a36Sopenharmony_ci		/* left/right diff:PGA/MUX */
27862306a36Sopenharmony_ci		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A);
27962306a36Sopenharmony_ci		ret = snd_soc_add_component_controls(component, ad1836_controls,
28062306a36Sopenharmony_ci				ARRAY_SIZE(ad1836_controls));
28162306a36Sopenharmony_ci		if (ret)
28262306a36Sopenharmony_ci			return ret;
28362306a36Sopenharmony_ci	} else {
28462306a36Sopenharmony_ci		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00);
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	ret = snd_soc_add_component_controls(component, ad183x_dac_controls, num_dacs * 2);
28862306a36Sopenharmony_ci	if (ret)
28962306a36Sopenharmony_ci		return ret;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	ret = snd_soc_add_component_controls(component, ad183x_adc_controls, num_adcs);
29262306a36Sopenharmony_ci	if (ret)
29362306a36Sopenharmony_ci		return ret;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);
29662306a36Sopenharmony_ci	if (ret)
29762306a36Sopenharmony_ci		return ret;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);
30062306a36Sopenharmony_ci	if (ret)
30162306a36Sopenharmony_ci		return ret;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);
30462306a36Sopenharmony_ci	if (ret)
30562306a36Sopenharmony_ci		return ret;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	return ret;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/* power down chip */
31362306a36Sopenharmony_cistatic void ad1836_remove(struct snd_soc_component *component)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);
31662306a36Sopenharmony_ci	/* reset clock control mode */
31762306a36Sopenharmony_ci	regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,
31862306a36Sopenharmony_ci		AD1836_ADC_SERFMT_MASK, 0);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_ad1836 = {
32262306a36Sopenharmony_ci	.probe			= ad1836_probe,
32362306a36Sopenharmony_ci	.remove			= ad1836_remove,
32462306a36Sopenharmony_ci	.suspend		= ad1836_suspend,
32562306a36Sopenharmony_ci	.resume			= ad1836_resume,
32662306a36Sopenharmony_ci	.controls		= ad183x_controls,
32762306a36Sopenharmony_ci	.num_controls		= ARRAY_SIZE(ad183x_controls),
32862306a36Sopenharmony_ci	.dapm_widgets		= ad183x_dapm_widgets,
32962306a36Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(ad183x_dapm_widgets),
33062306a36Sopenharmony_ci	.dapm_routes		= ad183x_dapm_routes,
33162306a36Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(ad183x_dapm_routes),
33262306a36Sopenharmony_ci	.idle_bias_on		= 1,
33362306a36Sopenharmony_ci	.use_pmdown_time	= 1,
33462306a36Sopenharmony_ci	.endianness		= 1,
33562306a36Sopenharmony_ci};
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic const struct reg_default ad1836_reg_defaults[] = {
33862306a36Sopenharmony_ci	{ AD1836_DAC_CTRL1, 0x0000 },
33962306a36Sopenharmony_ci	{ AD1836_DAC_CTRL2, 0x0000 },
34062306a36Sopenharmony_ci	{ AD1836_DAC_L_VOL(0), 0x0000 },
34162306a36Sopenharmony_ci	{ AD1836_DAC_R_VOL(0), 0x0000 },
34262306a36Sopenharmony_ci	{ AD1836_DAC_L_VOL(1), 0x0000 },
34362306a36Sopenharmony_ci	{ AD1836_DAC_R_VOL(1), 0x0000 },
34462306a36Sopenharmony_ci	{ AD1836_DAC_L_VOL(2), 0x0000 },
34562306a36Sopenharmony_ci	{ AD1836_DAC_R_VOL(2), 0x0000 },
34662306a36Sopenharmony_ci	{ AD1836_DAC_L_VOL(3), 0x0000 },
34762306a36Sopenharmony_ci	{ AD1836_DAC_R_VOL(3), 0x0000 },
34862306a36Sopenharmony_ci	{ AD1836_ADC_CTRL1, 0x0000 },
34962306a36Sopenharmony_ci	{ AD1836_ADC_CTRL2, 0x0000 },
35062306a36Sopenharmony_ci	{ AD1836_ADC_CTRL3, 0x0000 },
35162306a36Sopenharmony_ci};
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cistatic const struct regmap_config ad1836_regmap_config = {
35462306a36Sopenharmony_ci	.val_bits = 12,
35562306a36Sopenharmony_ci	.reg_bits = 4,
35662306a36Sopenharmony_ci	.read_flag_mask = 0x08,
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	.max_register = AD1836_ADC_CTRL3,
35962306a36Sopenharmony_ci	.reg_defaults = ad1836_reg_defaults,
36062306a36Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults),
36162306a36Sopenharmony_ci	.cache_type = REGCACHE_MAPLE,
36262306a36Sopenharmony_ci};
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic int ad1836_spi_probe(struct spi_device *spi)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	struct ad1836_priv *ad1836;
36762306a36Sopenharmony_ci	int ret;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv),
37062306a36Sopenharmony_ci			      GFP_KERNEL);
37162306a36Sopenharmony_ci	if (ad1836 == NULL)
37262306a36Sopenharmony_ci		return -ENOMEM;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config);
37562306a36Sopenharmony_ci	if (IS_ERR(ad1836->regmap))
37662306a36Sopenharmony_ci		return PTR_ERR(ad1836->regmap);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	ad1836->type = spi_get_device_id(spi)->driver_data;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	spi_set_drvdata(spi, ad1836);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	ret = devm_snd_soc_register_component(&spi->dev,
38362306a36Sopenharmony_ci			&soc_component_dev_ad1836, &ad183x_dais[ad1836->type], 1);
38462306a36Sopenharmony_ci	return ret;
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic const struct spi_device_id ad1836_ids[] = {
38862306a36Sopenharmony_ci	{ "ad1835", AD1835 },
38962306a36Sopenharmony_ci	{ "ad1836", AD1836 },
39062306a36Sopenharmony_ci	{ "ad1837", AD1835 },
39162306a36Sopenharmony_ci	{ "ad1838", AD1838 },
39262306a36Sopenharmony_ci	{ "ad1839", AD1838 },
39362306a36Sopenharmony_ci	{ },
39462306a36Sopenharmony_ci};
39562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad1836_ids);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic struct spi_driver ad1836_spi_driver = {
39862306a36Sopenharmony_ci	.driver = {
39962306a36Sopenharmony_ci		.name	= "ad1836",
40062306a36Sopenharmony_ci	},
40162306a36Sopenharmony_ci	.probe		= ad1836_spi_probe,
40262306a36Sopenharmony_ci	.id_table	= ad1836_ids,
40362306a36Sopenharmony_ci};
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cimodule_spi_driver(ad1836_spi_driver);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC ad1836 driver");
40862306a36Sopenharmony_ciMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
40962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
410