162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * NAU85L40 ALSA SoC audio driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2016 Nuvoton Technology Corp.
662306a36Sopenharmony_ci * Author: John Hsu <KCHSU0@nuvoton.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/moduleparam.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/pm.h>
1462306a36Sopenharmony_ci#include <linux/i2c.h>
1562306a36Sopenharmony_ci#include <linux/regmap.h>
1662306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1762306a36Sopenharmony_ci#include <linux/spi/spi.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/of_device.h>
2062306a36Sopenharmony_ci#include <sound/core.h>
2162306a36Sopenharmony_ci#include <sound/pcm.h>
2262306a36Sopenharmony_ci#include <sound/pcm_params.h>
2362306a36Sopenharmony_ci#include <sound/soc.h>
2462306a36Sopenharmony_ci#include <sound/soc-dapm.h>
2562306a36Sopenharmony_ci#include <sound/initval.h>
2662306a36Sopenharmony_ci#include <sound/tlv.h>
2762306a36Sopenharmony_ci#include "nau8540.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define NAU_FREF_MAX 13500000
3162306a36Sopenharmony_ci#define NAU_FVCO_MAX 100000000
3262306a36Sopenharmony_ci#define NAU_FVCO_MIN 90000000
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* the maximum frequency of CLK_ADC */
3562306a36Sopenharmony_ci#define CLK_ADC_MAX 6144000
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* scaling for mclk from sysclk_src output */
3862306a36Sopenharmony_cistatic const struct nau8540_fll_attr mclk_src_scaling[] = {
3962306a36Sopenharmony_ci	{ 1, 0x0 },
4062306a36Sopenharmony_ci	{ 2, 0x2 },
4162306a36Sopenharmony_ci	{ 4, 0x3 },
4262306a36Sopenharmony_ci	{ 8, 0x4 },
4362306a36Sopenharmony_ci	{ 16, 0x5 },
4462306a36Sopenharmony_ci	{ 32, 0x6 },
4562306a36Sopenharmony_ci	{ 3, 0x7 },
4662306a36Sopenharmony_ci	{ 6, 0xa },
4762306a36Sopenharmony_ci	{ 12, 0xb },
4862306a36Sopenharmony_ci	{ 24, 0xc },
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* ratio for input clk freq */
5262306a36Sopenharmony_cistatic const struct nau8540_fll_attr fll_ratio[] = {
5362306a36Sopenharmony_ci	{ 512000, 0x01 },
5462306a36Sopenharmony_ci	{ 256000, 0x02 },
5562306a36Sopenharmony_ci	{ 128000, 0x04 },
5662306a36Sopenharmony_ci	{ 64000, 0x08 },
5762306a36Sopenharmony_ci	{ 32000, 0x10 },
5862306a36Sopenharmony_ci	{ 8000, 0x20 },
5962306a36Sopenharmony_ci	{ 4000, 0x40 },
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic const struct nau8540_fll_attr fll_pre_scalar[] = {
6362306a36Sopenharmony_ci	{ 1, 0x0 },
6462306a36Sopenharmony_ci	{ 2, 0x1 },
6562306a36Sopenharmony_ci	{ 4, 0x2 },
6662306a36Sopenharmony_ci	{ 8, 0x3 },
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/* over sampling rate */
7062306a36Sopenharmony_cistatic const struct nau8540_osr_attr osr_adc_sel[] = {
7162306a36Sopenharmony_ci	{ 32, 3 },	/* OSR 32, SRC 1/8 */
7262306a36Sopenharmony_ci	{ 64, 2 },	/* OSR 64, SRC 1/4 */
7362306a36Sopenharmony_ci	{ 128, 1 },	/* OSR 128, SRC 1/2 */
7462306a36Sopenharmony_ci	{ 256, 0 },	/* OSR 256, SRC 1 */
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic const struct reg_default nau8540_reg_defaults[] = {
7862306a36Sopenharmony_ci	{NAU8540_REG_POWER_MANAGEMENT, 0x0000},
7962306a36Sopenharmony_ci	{NAU8540_REG_CLOCK_CTRL, 0x0000},
8062306a36Sopenharmony_ci	{NAU8540_REG_CLOCK_SRC, 0x0000},
8162306a36Sopenharmony_ci	{NAU8540_REG_FLL1, 0x0001},
8262306a36Sopenharmony_ci	{NAU8540_REG_FLL2, 0x3126},
8362306a36Sopenharmony_ci	{NAU8540_REG_FLL3, 0x0008},
8462306a36Sopenharmony_ci	{NAU8540_REG_FLL4, 0x0010},
8562306a36Sopenharmony_ci	{NAU8540_REG_FLL5, 0xC000},
8662306a36Sopenharmony_ci	{NAU8540_REG_FLL6, 0x6000},
8762306a36Sopenharmony_ci	{NAU8540_REG_FLL_VCO_RSV, 0xF13C},
8862306a36Sopenharmony_ci	{NAU8540_REG_PCM_CTRL0, 0x000B},
8962306a36Sopenharmony_ci	{NAU8540_REG_PCM_CTRL1, 0x3010},
9062306a36Sopenharmony_ci	{NAU8540_REG_PCM_CTRL2, 0x0800},
9162306a36Sopenharmony_ci	{NAU8540_REG_PCM_CTRL3, 0x0000},
9262306a36Sopenharmony_ci	{NAU8540_REG_PCM_CTRL4, 0x000F},
9362306a36Sopenharmony_ci	{NAU8540_REG_ALC_CONTROL_1, 0x0000},
9462306a36Sopenharmony_ci	{NAU8540_REG_ALC_CONTROL_2, 0x700B},
9562306a36Sopenharmony_ci	{NAU8540_REG_ALC_CONTROL_3, 0x0022},
9662306a36Sopenharmony_ci	{NAU8540_REG_ALC_CONTROL_4, 0x1010},
9762306a36Sopenharmony_ci	{NAU8540_REG_ALC_CONTROL_5, 0x1010},
9862306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL1_CH1, 0x0000},
9962306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL2_CH1, 0x0000},
10062306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL1_CH2, 0x0000},
10162306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL2_CH2, 0x0000},
10262306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL1_CH3, 0x0000},
10362306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL2_CH3, 0x0000},
10462306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL1_CH4, 0x0000},
10562306a36Sopenharmony_ci	{NAU8540_REG_NOTCH_FIL2_CH4, 0x0000},
10662306a36Sopenharmony_ci	{NAU8540_REG_HPF_FILTER_CH12, 0x0000},
10762306a36Sopenharmony_ci	{NAU8540_REG_HPF_FILTER_CH34, 0x0000},
10862306a36Sopenharmony_ci	{NAU8540_REG_ADC_SAMPLE_RATE, 0x0002},
10962306a36Sopenharmony_ci	{NAU8540_REG_DIGITAL_GAIN_CH1, 0x0400},
11062306a36Sopenharmony_ci	{NAU8540_REG_DIGITAL_GAIN_CH2, 0x0400},
11162306a36Sopenharmony_ci	{NAU8540_REG_DIGITAL_GAIN_CH3, 0x0400},
11262306a36Sopenharmony_ci	{NAU8540_REG_DIGITAL_GAIN_CH4, 0x0400},
11362306a36Sopenharmony_ci	{NAU8540_REG_DIGITAL_MUX, 0x00E4},
11462306a36Sopenharmony_ci	{NAU8540_REG_GPIO_CTRL, 0x0000},
11562306a36Sopenharmony_ci	{NAU8540_REG_MISC_CTRL, 0x0000},
11662306a36Sopenharmony_ci	{NAU8540_REG_I2C_CTRL, 0xEFFF},
11762306a36Sopenharmony_ci	{NAU8540_REG_VMID_CTRL, 0x0000},
11862306a36Sopenharmony_ci	{NAU8540_REG_MUTE, 0x0000},
11962306a36Sopenharmony_ci	{NAU8540_REG_ANALOG_ADC1, 0x0011},
12062306a36Sopenharmony_ci	{NAU8540_REG_ANALOG_ADC2, 0x0020},
12162306a36Sopenharmony_ci	{NAU8540_REG_ANALOG_PWR, 0x0000},
12262306a36Sopenharmony_ci	{NAU8540_REG_MIC_BIAS, 0x0004},
12362306a36Sopenharmony_ci	{NAU8540_REG_REFERENCE, 0x0000},
12462306a36Sopenharmony_ci	{NAU8540_REG_FEPGA1, 0x0000},
12562306a36Sopenharmony_ci	{NAU8540_REG_FEPGA2, 0x0000},
12662306a36Sopenharmony_ci	{NAU8540_REG_FEPGA3, 0x0101},
12762306a36Sopenharmony_ci	{NAU8540_REG_FEPGA4, 0x0101},
12862306a36Sopenharmony_ci	{NAU8540_REG_PWR, 0x0000},
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic bool nau8540_readable_reg(struct device *dev, unsigned int reg)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	switch (reg) {
13462306a36Sopenharmony_ci	case NAU8540_REG_POWER_MANAGEMENT ... NAU8540_REG_FLL_VCO_RSV:
13562306a36Sopenharmony_ci	case NAU8540_REG_PCM_CTRL0 ... NAU8540_REG_PCM_CTRL4:
13662306a36Sopenharmony_ci	case NAU8540_REG_ALC_CONTROL_1 ... NAU8540_REG_ALC_CONTROL_5:
13762306a36Sopenharmony_ci	case NAU8540_REG_ALC_GAIN_CH12 ... NAU8540_REG_ADC_SAMPLE_RATE:
13862306a36Sopenharmony_ci	case NAU8540_REG_DIGITAL_GAIN_CH1 ... NAU8540_REG_DIGITAL_MUX:
13962306a36Sopenharmony_ci	case NAU8540_REG_P2P_CH1 ... NAU8540_REG_I2C_CTRL:
14062306a36Sopenharmony_ci	case NAU8540_REG_I2C_DEVICE_ID:
14162306a36Sopenharmony_ci	case NAU8540_REG_VMID_CTRL ... NAU8540_REG_MUTE:
14262306a36Sopenharmony_ci	case NAU8540_REG_ANALOG_ADC1 ... NAU8540_REG_PWR:
14362306a36Sopenharmony_ci		return true;
14462306a36Sopenharmony_ci	default:
14562306a36Sopenharmony_ci		return false;
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic bool nau8540_writeable_reg(struct device *dev, unsigned int reg)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	switch (reg) {
15362306a36Sopenharmony_ci	case NAU8540_REG_SW_RESET ... NAU8540_REG_FLL_VCO_RSV:
15462306a36Sopenharmony_ci	case NAU8540_REG_PCM_CTRL0 ... NAU8540_REG_PCM_CTRL4:
15562306a36Sopenharmony_ci	case NAU8540_REG_ALC_CONTROL_1 ... NAU8540_REG_ALC_CONTROL_5:
15662306a36Sopenharmony_ci	case NAU8540_REG_NOTCH_FIL1_CH1 ... NAU8540_REG_ADC_SAMPLE_RATE:
15762306a36Sopenharmony_ci	case NAU8540_REG_DIGITAL_GAIN_CH1 ... NAU8540_REG_DIGITAL_MUX:
15862306a36Sopenharmony_ci	case NAU8540_REG_GPIO_CTRL ... NAU8540_REG_I2C_CTRL:
15962306a36Sopenharmony_ci	case NAU8540_REG_RST:
16062306a36Sopenharmony_ci	case NAU8540_REG_VMID_CTRL ... NAU8540_REG_MUTE:
16162306a36Sopenharmony_ci	case NAU8540_REG_ANALOG_ADC1 ... NAU8540_REG_PWR:
16262306a36Sopenharmony_ci		return true;
16362306a36Sopenharmony_ci	default:
16462306a36Sopenharmony_ci		return false;
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic bool nau8540_volatile_reg(struct device *dev, unsigned int reg)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	switch (reg) {
17162306a36Sopenharmony_ci	case NAU8540_REG_SW_RESET:
17262306a36Sopenharmony_ci	case NAU8540_REG_ALC_GAIN_CH12 ... NAU8540_REG_ALC_STATUS:
17362306a36Sopenharmony_ci	case NAU8540_REG_P2P_CH1 ... NAU8540_REG_PEAK_CH4:
17462306a36Sopenharmony_ci	case NAU8540_REG_I2C_DEVICE_ID:
17562306a36Sopenharmony_ci	case NAU8540_REG_RST:
17662306a36Sopenharmony_ci		return true;
17762306a36Sopenharmony_ci	default:
17862306a36Sopenharmony_ci		return false;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -12800, 3600);
18462306a36Sopenharmony_cistatic const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic const struct snd_kcontrol_new nau8540_snd_controls[] = {
18762306a36Sopenharmony_ci	SOC_SINGLE_TLV("Mic1 Volume", NAU8540_REG_DIGITAL_GAIN_CH1,
18862306a36Sopenharmony_ci		0, 0x520, 0, adc_vol_tlv),
18962306a36Sopenharmony_ci	SOC_SINGLE_TLV("Mic2 Volume", NAU8540_REG_DIGITAL_GAIN_CH2,
19062306a36Sopenharmony_ci		0, 0x520, 0, adc_vol_tlv),
19162306a36Sopenharmony_ci	SOC_SINGLE_TLV("Mic3 Volume", NAU8540_REG_DIGITAL_GAIN_CH3,
19262306a36Sopenharmony_ci		0, 0x520, 0, adc_vol_tlv),
19362306a36Sopenharmony_ci	SOC_SINGLE_TLV("Mic4 Volume", NAU8540_REG_DIGITAL_GAIN_CH4,
19462306a36Sopenharmony_ci		0, 0x520, 0, adc_vol_tlv),
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	SOC_SINGLE_TLV("Frontend PGA1 Volume", NAU8540_REG_FEPGA3,
19762306a36Sopenharmony_ci		0, 0x25, 0, fepga_gain_tlv),
19862306a36Sopenharmony_ci	SOC_SINGLE_TLV("Frontend PGA2 Volume", NAU8540_REG_FEPGA3,
19962306a36Sopenharmony_ci		8, 0x25, 0, fepga_gain_tlv),
20062306a36Sopenharmony_ci	SOC_SINGLE_TLV("Frontend PGA3 Volume", NAU8540_REG_FEPGA4,
20162306a36Sopenharmony_ci		0, 0x25, 0, fepga_gain_tlv),
20262306a36Sopenharmony_ci	SOC_SINGLE_TLV("Frontend PGA4 Volume", NAU8540_REG_FEPGA4,
20362306a36Sopenharmony_ci		8, 0x25, 0, fepga_gain_tlv),
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic const char * const adc_channel[] = {
20762306a36Sopenharmony_ci	"ADC channel 1", "ADC channel 2", "ADC channel 3", "ADC channel 4"
20862306a36Sopenharmony_ci};
20962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
21062306a36Sopenharmony_ci	digital_ch4_enum, NAU8540_REG_DIGITAL_MUX, 6, adc_channel);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic const struct snd_kcontrol_new digital_ch4_mux =
21362306a36Sopenharmony_ci	SOC_DAPM_ENUM("Digital CH4 Select", digital_ch4_enum);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
21662306a36Sopenharmony_ci	digital_ch3_enum, NAU8540_REG_DIGITAL_MUX, 4, adc_channel);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic const struct snd_kcontrol_new digital_ch3_mux =
21962306a36Sopenharmony_ci	SOC_DAPM_ENUM("Digital CH3 Select", digital_ch3_enum);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
22262306a36Sopenharmony_ci	digital_ch2_enum, NAU8540_REG_DIGITAL_MUX, 2, adc_channel);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic const struct snd_kcontrol_new digital_ch2_mux =
22562306a36Sopenharmony_ci	SOC_DAPM_ENUM("Digital CH2 Select", digital_ch2_enum);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
22862306a36Sopenharmony_ci	digital_ch1_enum, NAU8540_REG_DIGITAL_MUX, 0, adc_channel);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic const struct snd_kcontrol_new digital_ch1_mux =
23162306a36Sopenharmony_ci	SOC_DAPM_ENUM("Digital CH1 Select", digital_ch1_enum);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistatic int adc_power_control(struct snd_soc_dapm_widget *w,
23462306a36Sopenharmony_ci		struct snd_kcontrol *k, int  event)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
23762306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	if (SND_SOC_DAPM_EVENT_ON(event)) {
24062306a36Sopenharmony_ci		msleep(300);
24162306a36Sopenharmony_ci		/* DO12 and DO34 pad output enable */
24262306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
24362306a36Sopenharmony_ci			NAU8540_I2S_DO12_TRI, 0);
24462306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
24562306a36Sopenharmony_ci			NAU8540_I2S_DO34_TRI, 0);
24662306a36Sopenharmony_ci	} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
24762306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
24862306a36Sopenharmony_ci			NAU8540_I2S_DO12_TRI, NAU8540_I2S_DO12_TRI);
24962306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
25062306a36Sopenharmony_ci			NAU8540_I2S_DO34_TRI, NAU8540_I2S_DO34_TRI);
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci	return 0;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic int aiftx_power_control(struct snd_soc_dapm_widget *w,
25662306a36Sopenharmony_ci		struct snd_kcontrol *k, int  event)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
25962306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (SND_SOC_DAPM_EVENT_OFF(event)) {
26262306a36Sopenharmony_ci		regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0001);
26362306a36Sopenharmony_ci		regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0000);
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_ci	return 0;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
26962306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MICBIAS2", NAU8540_REG_MIC_BIAS, 11, 0, NULL, 0),
27062306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MICBIAS1", NAU8540_REG_MIC_BIAS, 10, 0, NULL, 0),
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC1"),
27362306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC2"),
27462306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC3"),
27562306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC4"),
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("Frontend PGA1", NAU8540_REG_PWR, 12, 0, NULL, 0),
27862306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("Frontend PGA2", NAU8540_REG_PWR, 13, 0, NULL, 0),
27962306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("Frontend PGA3", NAU8540_REG_PWR, 14, 0, NULL, 0),
28062306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("Frontend PGA4", NAU8540_REG_PWR, 15, 0, NULL, 0),
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC1", NULL,
28362306a36Sopenharmony_ci		NAU8540_REG_POWER_MANAGEMENT, 0, 0, adc_power_control,
28462306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
28562306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC2", NULL,
28662306a36Sopenharmony_ci		NAU8540_REG_POWER_MANAGEMENT, 1, 0, adc_power_control,
28762306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
28862306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC3", NULL,
28962306a36Sopenharmony_ci		NAU8540_REG_POWER_MANAGEMENT, 2, 0, adc_power_control,
29062306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
29162306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC4", NULL,
29262306a36Sopenharmony_ci		NAU8540_REG_POWER_MANAGEMENT, 3, 0, adc_power_control,
29362306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("ADC CH1", NAU8540_REG_ANALOG_PWR, 0, 0, NULL, 0),
29662306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("ADC CH2", NAU8540_REG_ANALOG_PWR, 1, 0, NULL, 0),
29762306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("ADC CH3", NAU8540_REG_ANALOG_PWR, 2, 0, NULL, 0),
29862306a36Sopenharmony_ci	SND_SOC_DAPM_PGA("ADC CH4", NAU8540_REG_ANALOG_PWR, 3, 0, NULL, 0),
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("Digital CH4 Mux",
30162306a36Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &digital_ch4_mux),
30262306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("Digital CH3 Mux",
30362306a36Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &digital_ch3_mux),
30462306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("Digital CH2 Mux",
30562306a36Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &digital_ch2_mux),
30662306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("Digital CH1 Mux",
30762306a36Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &digital_ch1_mux),
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT_E("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0,
31062306a36Sopenharmony_ci		aiftx_power_control, SND_SOC_DAPM_POST_PMD),
31162306a36Sopenharmony_ci};
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
31462306a36Sopenharmony_ci	{"Frontend PGA1", NULL, "MIC1"},
31562306a36Sopenharmony_ci	{"Frontend PGA2", NULL, "MIC2"},
31662306a36Sopenharmony_ci	{"Frontend PGA3", NULL, "MIC3"},
31762306a36Sopenharmony_ci	{"Frontend PGA4", NULL, "MIC4"},
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	{"ADC1", NULL, "Frontend PGA1"},
32062306a36Sopenharmony_ci	{"ADC2", NULL, "Frontend PGA2"},
32162306a36Sopenharmony_ci	{"ADC3", NULL, "Frontend PGA3"},
32262306a36Sopenharmony_ci	{"ADC4", NULL, "Frontend PGA4"},
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	{"ADC CH1", NULL, "ADC1"},
32562306a36Sopenharmony_ci	{"ADC CH2", NULL, "ADC2"},
32662306a36Sopenharmony_ci	{"ADC CH3", NULL, "ADC3"},
32762306a36Sopenharmony_ci	{"ADC CH4", NULL, "ADC4"},
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	{"ADC1", NULL, "MICBIAS1"},
33062306a36Sopenharmony_ci	{"ADC2", NULL, "MICBIAS1"},
33162306a36Sopenharmony_ci	{"ADC3", NULL, "MICBIAS2"},
33262306a36Sopenharmony_ci	{"ADC4", NULL, "MICBIAS2"},
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	{"Digital CH1 Mux", "ADC channel 1", "ADC CH1"},
33562306a36Sopenharmony_ci	{"Digital CH1 Mux", "ADC channel 2", "ADC CH2"},
33662306a36Sopenharmony_ci	{"Digital CH1 Mux", "ADC channel 3", "ADC CH3"},
33762306a36Sopenharmony_ci	{"Digital CH1 Mux", "ADC channel 4", "ADC CH4"},
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	{"Digital CH2 Mux", "ADC channel 1", "ADC CH1"},
34062306a36Sopenharmony_ci	{"Digital CH2 Mux", "ADC channel 2", "ADC CH2"},
34162306a36Sopenharmony_ci	{"Digital CH2 Mux", "ADC channel 3", "ADC CH3"},
34262306a36Sopenharmony_ci	{"Digital CH2 Mux", "ADC channel 4", "ADC CH4"},
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	{"Digital CH3 Mux", "ADC channel 1", "ADC CH1"},
34562306a36Sopenharmony_ci	{"Digital CH3 Mux", "ADC channel 2", "ADC CH2"},
34662306a36Sopenharmony_ci	{"Digital CH3 Mux", "ADC channel 3", "ADC CH3"},
34762306a36Sopenharmony_ci	{"Digital CH3 Mux", "ADC channel 4", "ADC CH4"},
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	{"Digital CH4 Mux", "ADC channel 1", "ADC CH1"},
35062306a36Sopenharmony_ci	{"Digital CH4 Mux", "ADC channel 2", "ADC CH2"},
35162306a36Sopenharmony_ci	{"Digital CH4 Mux", "ADC channel 3", "ADC CH3"},
35262306a36Sopenharmony_ci	{"Digital CH4 Mux", "ADC channel 4", "ADC CH4"},
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	{"AIFTX", NULL, "Digital CH1 Mux"},
35562306a36Sopenharmony_ci	{"AIFTX", NULL, "Digital CH2 Mux"},
35662306a36Sopenharmony_ci	{"AIFTX", NULL, "Digital CH3 Mux"},
35762306a36Sopenharmony_ci	{"AIFTX", NULL, "Digital CH4 Mux"},
35862306a36Sopenharmony_ci};
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic const struct nau8540_osr_attr *
36162306a36Sopenharmony_cinau8540_get_osr(struct nau8540 *nau8540)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	unsigned int osr;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
36662306a36Sopenharmony_ci	osr &= NAU8540_ADC_OSR_MASK;
36762306a36Sopenharmony_ci	if (osr >= ARRAY_SIZE(osr_adc_sel))
36862306a36Sopenharmony_ci		return NULL;
36962306a36Sopenharmony_ci	return &osr_adc_sel[osr];
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic int nau8540_dai_startup(struct snd_pcm_substream *substream,
37362306a36Sopenharmony_ci			       struct snd_soc_dai *dai)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
37662306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
37762306a36Sopenharmony_ci	const struct nau8540_osr_attr *osr;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	osr = nau8540_get_osr(nau8540);
38062306a36Sopenharmony_ci	if (!osr || !osr->osr)
38162306a36Sopenharmony_ci		return -EINVAL;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	return snd_pcm_hw_constraint_minmax(substream->runtime,
38462306a36Sopenharmony_ci					    SNDRV_PCM_HW_PARAM_RATE,
38562306a36Sopenharmony_ci					    0, CLK_ADC_MAX / osr->osr);
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic int nau8540_hw_params(struct snd_pcm_substream *substream,
38962306a36Sopenharmony_ci	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
39262306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
39362306a36Sopenharmony_ci	unsigned int val_len = 0;
39462306a36Sopenharmony_ci	const struct nau8540_osr_attr *osr;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	/* CLK_ADC = OSR * FS
39762306a36Sopenharmony_ci	 * ADC clock frequency is defined as Over Sampling Rate (OSR)
39862306a36Sopenharmony_ci	 * multiplied by the audio sample rate (Fs). Note that the OSR and Fs
39962306a36Sopenharmony_ci	 * values must be selected such that the maximum frequency is less
40062306a36Sopenharmony_ci	 * than 6.144 MHz.
40162306a36Sopenharmony_ci	 */
40262306a36Sopenharmony_ci	osr = nau8540_get_osr(nau8540);
40362306a36Sopenharmony_ci	if (!osr || !osr->osr)
40462306a36Sopenharmony_ci		return -EINVAL;
40562306a36Sopenharmony_ci	if (params_rate(params) * osr->osr > CLK_ADC_MAX)
40662306a36Sopenharmony_ci		return -EINVAL;
40762306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
40862306a36Sopenharmony_ci		NAU8540_CLK_ADC_SRC_MASK,
40962306a36Sopenharmony_ci		osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	switch (params_width(params)) {
41262306a36Sopenharmony_ci	case 16:
41362306a36Sopenharmony_ci		val_len |= NAU8540_I2S_DL_16;
41462306a36Sopenharmony_ci		break;
41562306a36Sopenharmony_ci	case 20:
41662306a36Sopenharmony_ci		val_len |= NAU8540_I2S_DL_20;
41762306a36Sopenharmony_ci		break;
41862306a36Sopenharmony_ci	case 24:
41962306a36Sopenharmony_ci		val_len |= NAU8540_I2S_DL_24;
42062306a36Sopenharmony_ci		break;
42162306a36Sopenharmony_ci	case 32:
42262306a36Sopenharmony_ci		val_len |= NAU8540_I2S_DL_32;
42362306a36Sopenharmony_ci		break;
42462306a36Sopenharmony_ci	default:
42562306a36Sopenharmony_ci		return -EINVAL;
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL0,
42962306a36Sopenharmony_ci		NAU8540_I2S_DL_MASK, val_len);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	return 0;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic int nau8540_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
43762306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
43862306a36Sopenharmony_ci	unsigned int ctrl1_val = 0, ctrl2_val = 0;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
44162306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
44262306a36Sopenharmony_ci		ctrl2_val |= NAU8540_I2S_MS_MASTER;
44362306a36Sopenharmony_ci		break;
44462306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBS_CFS:
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	default:
44762306a36Sopenharmony_ci		return -EINVAL;
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
45162306a36Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
45262306a36Sopenharmony_ci		break;
45362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
45462306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_BP_INV;
45562306a36Sopenharmony_ci		break;
45662306a36Sopenharmony_ci	default:
45762306a36Sopenharmony_ci		return -EINVAL;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
46162306a36Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
46262306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_DF_I2S;
46362306a36Sopenharmony_ci		break;
46462306a36Sopenharmony_ci	case SND_SOC_DAIFMT_LEFT_J:
46562306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_DF_LEFT;
46662306a36Sopenharmony_ci		break;
46762306a36Sopenharmony_ci	case SND_SOC_DAIFMT_RIGHT_J:
46862306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_DF_RIGTH;
46962306a36Sopenharmony_ci		break;
47062306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
47162306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_DF_PCM_AB;
47262306a36Sopenharmony_ci		break;
47362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_B:
47462306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_DF_PCM_AB;
47562306a36Sopenharmony_ci		ctrl1_val |= NAU8540_I2S_PCMB_EN;
47662306a36Sopenharmony_ci		break;
47762306a36Sopenharmony_ci	default:
47862306a36Sopenharmony_ci		return -EINVAL;
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL0,
48262306a36Sopenharmony_ci		NAU8540_I2S_DL_MASK | NAU8540_I2S_DF_MASK |
48362306a36Sopenharmony_ci		NAU8540_I2S_BP_INV | NAU8540_I2S_PCMB_EN, ctrl1_val);
48462306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
48562306a36Sopenharmony_ci		NAU8540_I2S_MS_MASK | NAU8540_I2S_DO12_OE, ctrl2_val);
48662306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
48762306a36Sopenharmony_ci		NAU8540_I2S_DO34_OE, 0);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	return 0;
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci/**
49362306a36Sopenharmony_ci * nau8540_set_tdm_slot - configure DAI TX TDM.
49462306a36Sopenharmony_ci * @dai: DAI
49562306a36Sopenharmony_ci * @tx_mask: bitmask representing active TX slots. Ex.
49662306a36Sopenharmony_ci *                 0xf for normal 4 channel TDM.
49762306a36Sopenharmony_ci *                 0xf0 for shifted 4 channel TDM
49862306a36Sopenharmony_ci * @rx_mask: no used.
49962306a36Sopenharmony_ci * @slots: Number of slots in use.
50062306a36Sopenharmony_ci * @slot_width: Width in bits for each slot.
50162306a36Sopenharmony_ci *
50262306a36Sopenharmony_ci * Configures a DAI for TDM operation. Only support 4 slots TDM.
50362306a36Sopenharmony_ci */
50462306a36Sopenharmony_cistatic int nau8540_set_tdm_slot(struct snd_soc_dai *dai,
50562306a36Sopenharmony_ci	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
50862306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
50962306a36Sopenharmony_ci	unsigned int ctrl2_val = 0, ctrl4_val = 0;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	if (slots > 4 || ((tx_mask & 0xf0) && (tx_mask & 0xf)))
51262306a36Sopenharmony_ci		return -EINVAL;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	ctrl4_val |= (NAU8540_TDM_MODE | NAU8540_TDM_OFFSET_EN);
51562306a36Sopenharmony_ci	if (tx_mask & 0xf0) {
51662306a36Sopenharmony_ci		ctrl2_val = 4 * slot_width;
51762306a36Sopenharmony_ci		ctrl4_val |= (tx_mask >> 4);
51862306a36Sopenharmony_ci	} else {
51962306a36Sopenharmony_ci		ctrl4_val |= tx_mask;
52062306a36Sopenharmony_ci	}
52162306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL4,
52262306a36Sopenharmony_ci		NAU8540_TDM_MODE | NAU8540_TDM_OFFSET_EN |
52362306a36Sopenharmony_ci		NAU8540_TDM_TX_MASK, ctrl4_val);
52462306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
52562306a36Sopenharmony_ci		NAU8540_I2S_DO12_OE, NAU8540_I2S_DO12_OE);
52662306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
52762306a36Sopenharmony_ci		NAU8540_I2S_DO34_OE | NAU8540_I2S_TSLOT_L_MASK,
52862306a36Sopenharmony_ci		NAU8540_I2S_DO34_OE | ctrl2_val);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	return 0;
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic const struct snd_soc_dai_ops nau8540_dai_ops = {
53562306a36Sopenharmony_ci	.startup = nau8540_dai_startup,
53662306a36Sopenharmony_ci	.hw_params = nau8540_hw_params,
53762306a36Sopenharmony_ci	.set_fmt = nau8540_set_fmt,
53862306a36Sopenharmony_ci	.set_tdm_slot = nau8540_set_tdm_slot,
53962306a36Sopenharmony_ci};
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci#define NAU8540_RATES SNDRV_PCM_RATE_8000_48000
54262306a36Sopenharmony_ci#define NAU8540_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
54362306a36Sopenharmony_ci	 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistatic struct snd_soc_dai_driver nau8540_dai = {
54662306a36Sopenharmony_ci	.name = "nau8540-hifi",
54762306a36Sopenharmony_ci	.capture = {
54862306a36Sopenharmony_ci		.stream_name = "Capture",
54962306a36Sopenharmony_ci		.channels_min = 1,
55062306a36Sopenharmony_ci		.channels_max = 4,
55162306a36Sopenharmony_ci		.rates = NAU8540_RATES,
55262306a36Sopenharmony_ci		.formats = NAU8540_FORMATS,
55362306a36Sopenharmony_ci	},
55462306a36Sopenharmony_ci	.ops = &nau8540_dai_ops,
55562306a36Sopenharmony_ci};
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci/**
55862306a36Sopenharmony_ci * nau8540_calc_fll_param - Calculate FLL parameters.
55962306a36Sopenharmony_ci * @fll_in: external clock provided to codec.
56062306a36Sopenharmony_ci * @fs: sampling rate.
56162306a36Sopenharmony_ci * @fll_param: Pointer to structure of FLL parameters.
56262306a36Sopenharmony_ci *
56362306a36Sopenharmony_ci * Calculate FLL parameters to configure codec.
56462306a36Sopenharmony_ci *
56562306a36Sopenharmony_ci * Returns 0 for success or negative error code.
56662306a36Sopenharmony_ci */
56762306a36Sopenharmony_cistatic int nau8540_calc_fll_param(unsigned int fll_in,
56862306a36Sopenharmony_ci	unsigned int fs, struct nau8540_fll *fll_param)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	u64 fvco, fvco_max;
57162306a36Sopenharmony_ci	unsigned int fref, i, fvco_sel;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	/* Ensure the reference clock frequency (FREF) is <= 13.5MHz by dividing
57462306a36Sopenharmony_ci	 * freq_in by 1, 2, 4, or 8 using FLL pre-scalar.
57562306a36Sopenharmony_ci	 * FREF = freq_in / NAU8540_FLL_REF_DIV_MASK
57662306a36Sopenharmony_ci	 */
57762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fll_pre_scalar); i++) {
57862306a36Sopenharmony_ci		fref = fll_in / fll_pre_scalar[i].param;
57962306a36Sopenharmony_ci		if (fref <= NAU_FREF_MAX)
58062306a36Sopenharmony_ci			break;
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci	if (i == ARRAY_SIZE(fll_pre_scalar))
58362306a36Sopenharmony_ci		return -EINVAL;
58462306a36Sopenharmony_ci	fll_param->clk_ref_div = fll_pre_scalar[i].val;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	/* Choose the FLL ratio based on FREF */
58762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fll_ratio); i++) {
58862306a36Sopenharmony_ci		if (fref >= fll_ratio[i].param)
58962306a36Sopenharmony_ci			break;
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci	if (i == ARRAY_SIZE(fll_ratio))
59262306a36Sopenharmony_ci		return -EINVAL;
59362306a36Sopenharmony_ci	fll_param->ratio = fll_ratio[i].val;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	/* Calculate the frequency of DCO (FDCO) given freq_out = 256 * Fs.
59662306a36Sopenharmony_ci	 * FDCO must be within the 90MHz - 124MHz or the FFL cannot be
59762306a36Sopenharmony_ci	 * guaranteed across the full range of operation.
59862306a36Sopenharmony_ci	 * FDCO = freq_out * 2 * mclk_src_scaling
59962306a36Sopenharmony_ci	 */
60062306a36Sopenharmony_ci	fvco_max = 0;
60162306a36Sopenharmony_ci	fvco_sel = ARRAY_SIZE(mclk_src_scaling);
60262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) {
60362306a36Sopenharmony_ci		fvco = 256ULL * fs * 2 * mclk_src_scaling[i].param;
60462306a36Sopenharmony_ci		if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX &&
60562306a36Sopenharmony_ci			fvco_max < fvco) {
60662306a36Sopenharmony_ci			fvco_max = fvco;
60762306a36Sopenharmony_ci			fvco_sel = i;
60862306a36Sopenharmony_ci		}
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci	if (ARRAY_SIZE(mclk_src_scaling) == fvco_sel)
61162306a36Sopenharmony_ci		return -EINVAL;
61262306a36Sopenharmony_ci	fll_param->mclk_src = mclk_src_scaling[fvco_sel].val;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	/* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional
61562306a36Sopenharmony_ci	 * input based on FDCO, FREF and FLL ratio.
61662306a36Sopenharmony_ci	 */
61762306a36Sopenharmony_ci	fvco = div_u64(fvco_max << 16, fref * fll_param->ratio);
61862306a36Sopenharmony_ci	fll_param->fll_int = (fvco >> 16) & 0x3FF;
61962306a36Sopenharmony_ci	fll_param->fll_frac = fvco & 0xFFFF;
62062306a36Sopenharmony_ci	return 0;
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_cistatic void nau8540_fll_apply(struct regmap *regmap,
62462306a36Sopenharmony_ci	struct nau8540_fll *fll_param)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_CLOCK_SRC,
62762306a36Sopenharmony_ci		NAU8540_CLK_SRC_MASK | NAU8540_CLK_MCLK_SRC_MASK,
62862306a36Sopenharmony_ci		NAU8540_CLK_SRC_MCLK | fll_param->mclk_src);
62962306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FLL1,
63062306a36Sopenharmony_ci		NAU8540_FLL_RATIO_MASK | NAU8540_ICTRL_LATCH_MASK,
63162306a36Sopenharmony_ci		fll_param->ratio | (0x6 << NAU8540_ICTRL_LATCH_SFT));
63262306a36Sopenharmony_ci	/* FLL 16-bit fractional input */
63362306a36Sopenharmony_ci	regmap_write(regmap, NAU8540_REG_FLL2, fll_param->fll_frac);
63462306a36Sopenharmony_ci	/* FLL 10-bit integer input */
63562306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FLL3,
63662306a36Sopenharmony_ci		NAU8540_FLL_INTEGER_MASK, fll_param->fll_int);
63762306a36Sopenharmony_ci	/* FLL pre-scaler */
63862306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FLL4,
63962306a36Sopenharmony_ci		NAU8540_FLL_REF_DIV_MASK,
64062306a36Sopenharmony_ci		fll_param->clk_ref_div << NAU8540_FLL_REF_DIV_SFT);
64162306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FLL5,
64262306a36Sopenharmony_ci		NAU8540_FLL_CLK_SW_MASK, NAU8540_FLL_CLK_SW_REF);
64362306a36Sopenharmony_ci	regmap_update_bits(regmap,
64462306a36Sopenharmony_ci		NAU8540_REG_FLL6, NAU8540_DCO_EN, 0);
64562306a36Sopenharmony_ci	if (fll_param->fll_frac) {
64662306a36Sopenharmony_ci		regmap_update_bits(regmap, NAU8540_REG_FLL5,
64762306a36Sopenharmony_ci			NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN |
64862306a36Sopenharmony_ci			NAU8540_FLL_FTR_SW_MASK,
64962306a36Sopenharmony_ci			NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN |
65062306a36Sopenharmony_ci			NAU8540_FLL_FTR_SW_FILTER);
65162306a36Sopenharmony_ci		regmap_update_bits(regmap, NAU8540_REG_FLL6,
65262306a36Sopenharmony_ci			NAU8540_SDM_EN | NAU8540_CUTOFF500,
65362306a36Sopenharmony_ci			NAU8540_SDM_EN | NAU8540_CUTOFF500);
65462306a36Sopenharmony_ci	} else {
65562306a36Sopenharmony_ci		regmap_update_bits(regmap, NAU8540_REG_FLL5,
65662306a36Sopenharmony_ci			NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN |
65762306a36Sopenharmony_ci			NAU8540_FLL_FTR_SW_MASK, NAU8540_FLL_FTR_SW_ACCU);
65862306a36Sopenharmony_ci		regmap_update_bits(regmap, NAU8540_REG_FLL6,
65962306a36Sopenharmony_ci			NAU8540_SDM_EN | NAU8540_CUTOFF500, 0);
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci/* freq_out must be 256*Fs in order to achieve the best performance */
66462306a36Sopenharmony_cistatic int nau8540_set_pll(struct snd_soc_component *component, int pll_id, int source,
66562306a36Sopenharmony_ci		unsigned int freq_in, unsigned int freq_out)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
66862306a36Sopenharmony_ci	struct nau8540_fll fll_param;
66962306a36Sopenharmony_ci	int ret, fs;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	switch (pll_id) {
67262306a36Sopenharmony_ci	case NAU8540_CLK_FLL_MCLK:
67362306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
67462306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
67562306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_MCLK | 0);
67662306a36Sopenharmony_ci		break;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	case NAU8540_CLK_FLL_BLK:
67962306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
68062306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
68162306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_BLK |
68262306a36Sopenharmony_ci			(0xf << NAU8540_GAIN_ERR_SFT));
68362306a36Sopenharmony_ci		break;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	case NAU8540_CLK_FLL_FS:
68662306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
68762306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
68862306a36Sopenharmony_ci			NAU8540_FLL_CLK_SRC_FS |
68962306a36Sopenharmony_ci			(0xf << NAU8540_GAIN_ERR_SFT));
69062306a36Sopenharmony_ci		break;
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	default:
69362306a36Sopenharmony_ci		dev_err(nau8540->dev, "Invalid clock id (%d)\n", pll_id);
69462306a36Sopenharmony_ci		return -EINVAL;
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci	dev_dbg(nau8540->dev, "Sysclk is %dHz and clock id is %d\n",
69762306a36Sopenharmony_ci		freq_out, pll_id);
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	fs = freq_out / 256;
70062306a36Sopenharmony_ci	ret = nau8540_calc_fll_param(freq_in, fs, &fll_param);
70162306a36Sopenharmony_ci	if (ret < 0) {
70262306a36Sopenharmony_ci		dev_err(nau8540->dev, "Unsupported input clock %d\n", freq_in);
70362306a36Sopenharmony_ci		return ret;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci	dev_dbg(nau8540->dev, "mclk_src=%x ratio=%x fll_frac=%x fll_int=%x clk_ref_div=%x\n",
70662306a36Sopenharmony_ci		fll_param.mclk_src, fll_param.ratio, fll_param.fll_frac,
70762306a36Sopenharmony_ci		fll_param.fll_int, fll_param.clk_ref_div);
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	nau8540_fll_apply(nau8540->regmap, &fll_param);
71062306a36Sopenharmony_ci	mdelay(2);
71162306a36Sopenharmony_ci	regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
71262306a36Sopenharmony_ci		NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_VCO);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	return 0;
71562306a36Sopenharmony_ci}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic int nau8540_set_sysclk(struct snd_soc_component *component,
71862306a36Sopenharmony_ci	int clk_id, int source, unsigned int freq, int dir)
71962306a36Sopenharmony_ci{
72062306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	switch (clk_id) {
72362306a36Sopenharmony_ci	case NAU8540_CLK_DIS:
72462306a36Sopenharmony_ci	case NAU8540_CLK_MCLK:
72562306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
72662306a36Sopenharmony_ci			NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_MCLK);
72762306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL6,
72862306a36Sopenharmony_ci			NAU8540_DCO_EN, 0);
72962306a36Sopenharmony_ci		break;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	case NAU8540_CLK_INTERNAL:
73262306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL6,
73362306a36Sopenharmony_ci			NAU8540_DCO_EN, NAU8540_DCO_EN);
73462306a36Sopenharmony_ci		regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
73562306a36Sopenharmony_ci			NAU8540_CLK_SRC_MASK, NAU8540_CLK_SRC_VCO);
73662306a36Sopenharmony_ci		break;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	default:
73962306a36Sopenharmony_ci		dev_err(nau8540->dev, "Invalid clock id (%d)\n", clk_id);
74062306a36Sopenharmony_ci		return -EINVAL;
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	dev_dbg(nau8540->dev, "Sysclk is %dHz and clock id is %d\n",
74462306a36Sopenharmony_ci		freq, clk_id);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	return 0;
74762306a36Sopenharmony_ci}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_cistatic void nau8540_reset_chip(struct regmap *regmap)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	regmap_write(regmap, NAU8540_REG_SW_RESET, 0x00);
75262306a36Sopenharmony_ci	regmap_write(regmap, NAU8540_REG_SW_RESET, 0x00);
75362306a36Sopenharmony_ci}
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic void nau8540_init_regs(struct nau8540 *nau8540)
75662306a36Sopenharmony_ci{
75762306a36Sopenharmony_ci	struct regmap *regmap = nau8540->regmap;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	/* Enable Bias/VMID/VMID Tieoff */
76062306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_VMID_CTRL,
76162306a36Sopenharmony_ci		NAU8540_VMID_EN | NAU8540_VMID_SEL_MASK,
76262306a36Sopenharmony_ci		NAU8540_VMID_EN | (0x2 << NAU8540_VMID_SEL_SFT));
76362306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_REFERENCE,
76462306a36Sopenharmony_ci		NAU8540_PRECHARGE_DIS | NAU8540_GLOBAL_BIAS_EN,
76562306a36Sopenharmony_ci		NAU8540_PRECHARGE_DIS | NAU8540_GLOBAL_BIAS_EN);
76662306a36Sopenharmony_ci	mdelay(2);
76762306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_MIC_BIAS,
76862306a36Sopenharmony_ci		NAU8540_PU_PRE, NAU8540_PU_PRE);
76962306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_CLOCK_CTRL,
77062306a36Sopenharmony_ci		NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN,
77162306a36Sopenharmony_ci		NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN);
77262306a36Sopenharmony_ci	/* ADC OSR selection, CLK_ADC = Fs * OSR;
77362306a36Sopenharmony_ci	 * Channel time alignment enable.
77462306a36Sopenharmony_ci	 */
77562306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_ADC_SAMPLE_RATE,
77662306a36Sopenharmony_ci		NAU8540_CH_SYNC | NAU8540_ADC_OSR_MASK,
77762306a36Sopenharmony_ci		NAU8540_CH_SYNC | NAU8540_ADC_OSR_64);
77862306a36Sopenharmony_ci	/* PGA input mode selection */
77962306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FEPGA1,
78062306a36Sopenharmony_ci		NAU8540_FEPGA1_MODCH2_SHT | NAU8540_FEPGA1_MODCH1_SHT,
78162306a36Sopenharmony_ci		NAU8540_FEPGA1_MODCH2_SHT | NAU8540_FEPGA1_MODCH1_SHT);
78262306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_FEPGA2,
78362306a36Sopenharmony_ci		NAU8540_FEPGA2_MODCH4_SHT | NAU8540_FEPGA2_MODCH3_SHT,
78462306a36Sopenharmony_ci		NAU8540_FEPGA2_MODCH4_SHT | NAU8540_FEPGA2_MODCH3_SHT);
78562306a36Sopenharmony_ci	/* DO12 and DO34 pad output disable */
78662306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_PCM_CTRL1,
78762306a36Sopenharmony_ci		NAU8540_I2S_DO12_TRI, NAU8540_I2S_DO12_TRI);
78862306a36Sopenharmony_ci	regmap_update_bits(regmap, NAU8540_REG_PCM_CTRL2,
78962306a36Sopenharmony_ci		NAU8540_I2S_DO34_TRI, NAU8540_I2S_DO34_TRI);
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_cistatic int __maybe_unused nau8540_suspend(struct snd_soc_component *component)
79362306a36Sopenharmony_ci{
79462306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	regcache_cache_only(nau8540->regmap, true);
79762306a36Sopenharmony_ci	regcache_mark_dirty(nau8540->regmap);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	return 0;
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_cistatic int __maybe_unused nau8540_resume(struct snd_soc_component *component)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	regcache_cache_only(nau8540->regmap, false);
80762306a36Sopenharmony_ci	regcache_sync(nau8540->regmap);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return 0;
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_cistatic const struct snd_soc_component_driver nau8540_component_driver = {
81362306a36Sopenharmony_ci	.set_sysclk		= nau8540_set_sysclk,
81462306a36Sopenharmony_ci	.set_pll		= nau8540_set_pll,
81562306a36Sopenharmony_ci	.suspend		= nau8540_suspend,
81662306a36Sopenharmony_ci	.resume			= nau8540_resume,
81762306a36Sopenharmony_ci	.controls		= nau8540_snd_controls,
81862306a36Sopenharmony_ci	.num_controls		= ARRAY_SIZE(nau8540_snd_controls),
81962306a36Sopenharmony_ci	.dapm_widgets		= nau8540_dapm_widgets,
82062306a36Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(nau8540_dapm_widgets),
82162306a36Sopenharmony_ci	.dapm_routes		= nau8540_dapm_routes,
82262306a36Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(nau8540_dapm_routes),
82362306a36Sopenharmony_ci	.suspend_bias_off	= 1,
82462306a36Sopenharmony_ci	.idle_bias_on		= 1,
82562306a36Sopenharmony_ci	.use_pmdown_time	= 1,
82662306a36Sopenharmony_ci	.endianness		= 1,
82762306a36Sopenharmony_ci};
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_cistatic const struct regmap_config nau8540_regmap_config = {
83062306a36Sopenharmony_ci	.val_bits = 16,
83162306a36Sopenharmony_ci	.reg_bits = 16,
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	.max_register = NAU8540_REG_MAX,
83462306a36Sopenharmony_ci	.readable_reg = nau8540_readable_reg,
83562306a36Sopenharmony_ci	.writeable_reg = nau8540_writeable_reg,
83662306a36Sopenharmony_ci	.volatile_reg = nau8540_volatile_reg,
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
83962306a36Sopenharmony_ci	.reg_defaults = nau8540_reg_defaults,
84062306a36Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(nau8540_reg_defaults),
84162306a36Sopenharmony_ci};
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_cistatic int nau8540_i2c_probe(struct i2c_client *i2c)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	struct device *dev = &i2c->dev;
84662306a36Sopenharmony_ci	struct nau8540 *nau8540 = dev_get_platdata(dev);
84762306a36Sopenharmony_ci	int ret, value;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	if (!nau8540) {
85062306a36Sopenharmony_ci		nau8540 = devm_kzalloc(dev, sizeof(*nau8540), GFP_KERNEL);
85162306a36Sopenharmony_ci		if (!nau8540)
85262306a36Sopenharmony_ci			return -ENOMEM;
85362306a36Sopenharmony_ci	}
85462306a36Sopenharmony_ci	i2c_set_clientdata(i2c, nau8540);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	nau8540->regmap = devm_regmap_init_i2c(i2c, &nau8540_regmap_config);
85762306a36Sopenharmony_ci	if (IS_ERR(nau8540->regmap))
85862306a36Sopenharmony_ci		return PTR_ERR(nau8540->regmap);
85962306a36Sopenharmony_ci	ret = regmap_read(nau8540->regmap, NAU8540_REG_I2C_DEVICE_ID, &value);
86062306a36Sopenharmony_ci	if (ret < 0) {
86162306a36Sopenharmony_ci		dev_err(dev, "Failed to read device id from the NAU85L40: %d\n",
86262306a36Sopenharmony_ci			ret);
86362306a36Sopenharmony_ci		return ret;
86462306a36Sopenharmony_ci	}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	nau8540->dev = dev;
86762306a36Sopenharmony_ci	nau8540_reset_chip(nau8540->regmap);
86862306a36Sopenharmony_ci	nau8540_init_regs(nau8540);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	return devm_snd_soc_register_component(dev,
87162306a36Sopenharmony_ci		&nau8540_component_driver, &nau8540_dai, 1);
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic const struct i2c_device_id nau8540_i2c_ids[] = {
87562306a36Sopenharmony_ci	{ "nau8540", 0 },
87662306a36Sopenharmony_ci	{ }
87762306a36Sopenharmony_ci};
87862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, nau8540_i2c_ids);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci#ifdef CONFIG_OF
88162306a36Sopenharmony_cistatic const struct of_device_id nau8540_of_ids[] = {
88262306a36Sopenharmony_ci	{ .compatible = "nuvoton,nau8540", },
88362306a36Sopenharmony_ci	{}
88462306a36Sopenharmony_ci};
88562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, nau8540_of_ids);
88662306a36Sopenharmony_ci#endif
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cistatic struct i2c_driver nau8540_i2c_driver = {
88962306a36Sopenharmony_ci	.driver = {
89062306a36Sopenharmony_ci		.name = "nau8540",
89162306a36Sopenharmony_ci		.of_match_table = of_match_ptr(nau8540_of_ids),
89262306a36Sopenharmony_ci	},
89362306a36Sopenharmony_ci	.probe = nau8540_i2c_probe,
89462306a36Sopenharmony_ci	.id_table = nau8540_i2c_ids,
89562306a36Sopenharmony_ci};
89662306a36Sopenharmony_cimodule_i2c_driver(nau8540_i2c_driver);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC NAU85L40 driver");
89962306a36Sopenharmony_ciMODULE_AUTHOR("John Hsu <KCHSU0@nuvoton.com>");
90062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
901