1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ADAU1977/ADAU1978/ADAU1979 driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2014 Analog Devices Inc.
6*4882a593Smuzhiyun * Author: Lars-Peter Clausen <lars@metafoo.de>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_data/adau1977.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <sound/core.h>
21*4882a593Smuzhiyun #include <sound/initval.h>
22*4882a593Smuzhiyun #include <sound/pcm.h>
23*4882a593Smuzhiyun #include <sound/pcm_params.h>
24*4882a593Smuzhiyun #include <sound/soc.h>
25*4882a593Smuzhiyun #include <sound/tlv.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include "adau1977.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define ADAU1977_REG_POWER 0x00
30*4882a593Smuzhiyun #define ADAU1977_REG_PLL 0x01
31*4882a593Smuzhiyun #define ADAU1977_REG_BOOST 0x02
32*4882a593Smuzhiyun #define ADAU1977_REG_MICBIAS 0x03
33*4882a593Smuzhiyun #define ADAU1977_REG_BLOCK_POWER_SAI 0x04
34*4882a593Smuzhiyun #define ADAU1977_REG_SAI_CTRL0 0x05
35*4882a593Smuzhiyun #define ADAU1977_REG_SAI_CTRL1 0x06
36*4882a593Smuzhiyun #define ADAU1977_REG_CMAP12 0x07
37*4882a593Smuzhiyun #define ADAU1977_REG_CMAP34 0x08
38*4882a593Smuzhiyun #define ADAU1977_REG_SAI_OVERTEMP 0x09
39*4882a593Smuzhiyun #define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x))
40*4882a593Smuzhiyun #define ADAU1977_REG_MISC_CONTROL 0x0e
41*4882a593Smuzhiyun #define ADAU1977_REG_DIAG_CONTROL 0x10
42*4882a593Smuzhiyun #define ADAU1977_REG_STATUS(x) (0x11 + (x))
43*4882a593Smuzhiyun #define ADAU1977_REG_DIAG_IRQ1 0x15
44*4882a593Smuzhiyun #define ADAU1977_REG_DIAG_IRQ2 0x16
45*4882a593Smuzhiyun #define ADAU1977_REG_ADJUST1 0x17
46*4882a593Smuzhiyun #define ADAU1977_REG_ADJUST2 0x18
47*4882a593Smuzhiyun #define ADAU1977_REG_ADC_CLIP 0x19
48*4882a593Smuzhiyun #define ADAU1977_REG_DC_HPF_CAL 0x1a
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define ADAU1977_POWER_RESET BIT(7)
51*4882a593Smuzhiyun #define ADAU1977_POWER_PWUP BIT(0)
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define ADAU1977_PLL_CLK_S BIT(4)
54*4882a593Smuzhiyun #define ADAU1977_PLL_MCS_MASK 0x7
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0
57*4882a593Smuzhiyun #define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7)
60*4882a593Smuzhiyun #define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6)
61*4882a593Smuzhiyun #define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5)
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6)
64*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6)
65*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6)
66*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6)
67*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6)
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3)
70*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3)
71*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3)
72*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3)
73*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3)
74*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3)
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_MASK (0x7)
77*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0)
78*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1)
79*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2)
80*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3)
81*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5)
84*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5)
85*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5)
86*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5)
87*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4)
88*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4)
89*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4)
90*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3)
91*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_MSB BIT(2)
92*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1)
93*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1)
94*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1)
95*4882a593Smuzhiyun #define ADAU1977_SAI_CTRL1_MASTER BIT(0)
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun #define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x))
98*4882a593Smuzhiyun #define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6)
101*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6)
102*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6)
103*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6)
104*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_MMUTE BIT(4)
105*4882a593Smuzhiyun #define ADAU1977_MISC_CONTROL_DC_CAL BIT(0)
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun #define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4
108*4882a593Smuzhiyun #define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun struct adau1977 {
111*4882a593Smuzhiyun struct regmap *regmap;
112*4882a593Smuzhiyun bool right_j;
113*4882a593Smuzhiyun unsigned int sysclk;
114*4882a593Smuzhiyun enum adau1977_sysclk_src sysclk_src;
115*4882a593Smuzhiyun struct gpio_desc *reset_gpio;
116*4882a593Smuzhiyun enum adau1977_type type;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun struct regulator *avdd_reg;
119*4882a593Smuzhiyun struct regulator *dvdd_reg;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun struct snd_pcm_hw_constraint_list constraints;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun struct device *dev;
124*4882a593Smuzhiyun void (*switch_mode)(struct device *dev);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun unsigned int max_master_fs;
127*4882a593Smuzhiyun unsigned int slot_width;
128*4882a593Smuzhiyun bool enabled;
129*4882a593Smuzhiyun bool master;
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static const struct reg_default adau1977_reg_defaults[] = {
133*4882a593Smuzhiyun { 0x00, 0x00 },
134*4882a593Smuzhiyun { 0x01, 0x41 },
135*4882a593Smuzhiyun { 0x02, 0x4a },
136*4882a593Smuzhiyun { 0x03, 0x7d },
137*4882a593Smuzhiyun { 0x04, 0x3d },
138*4882a593Smuzhiyun { 0x05, 0x02 },
139*4882a593Smuzhiyun { 0x06, 0x00 },
140*4882a593Smuzhiyun { 0x07, 0x10 },
141*4882a593Smuzhiyun { 0x08, 0x32 },
142*4882a593Smuzhiyun { 0x09, 0xf0 },
143*4882a593Smuzhiyun { 0x0a, 0xa0 },
144*4882a593Smuzhiyun { 0x0b, 0xa0 },
145*4882a593Smuzhiyun { 0x0c, 0xa0 },
146*4882a593Smuzhiyun { 0x0d, 0xa0 },
147*4882a593Smuzhiyun { 0x0e, 0x02 },
148*4882a593Smuzhiyun { 0x10, 0x0f },
149*4882a593Smuzhiyun { 0x15, 0x20 },
150*4882a593Smuzhiyun { 0x16, 0x00 },
151*4882a593Smuzhiyun { 0x17, 0x00 },
152*4882a593Smuzhiyun { 0x18, 0x00 },
153*4882a593Smuzhiyun { 0x1a, 0x00 },
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = {
159*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS,
160*4882a593Smuzhiyun 3, 0, NULL, 0)
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = {
164*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI,
165*4882a593Smuzhiyun 4, 0, NULL, 0),
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0),
168*4882a593Smuzhiyun SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0),
169*4882a593Smuzhiyun SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0),
170*4882a593Smuzhiyun SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0),
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("AIN1"),
173*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("AIN2"),
174*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("AIN3"),
175*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("AIN4"),
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("VREF"),
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun static const struct snd_soc_dapm_route adau1977_dapm_routes[] = {
181*4882a593Smuzhiyun { "ADC1", NULL, "AIN1" },
182*4882a593Smuzhiyun { "ADC2", NULL, "AIN2" },
183*4882a593Smuzhiyun { "ADC3", NULL, "AIN3" },
184*4882a593Smuzhiyun { "ADC4", NULL, "AIN4" },
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun { "ADC1", NULL, "Vref" },
187*4882a593Smuzhiyun { "ADC2", NULL, "Vref" },
188*4882a593Smuzhiyun { "ADC3", NULL, "Vref" },
189*4882a593Smuzhiyun { "ADC4", NULL, "Vref" },
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun { "VREF", NULL, "Vref" },
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun #define ADAU1977_VOLUME(x) \
195*4882a593Smuzhiyun SOC_SINGLE_TLV("ADC" #x " Capture Volume", \
196*4882a593Smuzhiyun ADAU1977_REG_POST_ADC_GAIN((x) - 1), \
197*4882a593Smuzhiyun 0, 255, 1, adau1977_adc_gain)
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #define ADAU1977_HPF_SWITCH(x) \
200*4882a593Smuzhiyun SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \
201*4882a593Smuzhiyun ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0)
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun #define ADAU1977_DC_SUB_SWITCH(x) \
204*4882a593Smuzhiyun SOC_SINGLE("ADC" #x " DC Subtraction Capture Switch", \
205*4882a593Smuzhiyun ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0)
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun static const struct snd_kcontrol_new adau1977_snd_controls[] = {
208*4882a593Smuzhiyun ADAU1977_VOLUME(1),
209*4882a593Smuzhiyun ADAU1977_VOLUME(2),
210*4882a593Smuzhiyun ADAU1977_VOLUME(3),
211*4882a593Smuzhiyun ADAU1977_VOLUME(4),
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun ADAU1977_HPF_SWITCH(1),
214*4882a593Smuzhiyun ADAU1977_HPF_SWITCH(2),
215*4882a593Smuzhiyun ADAU1977_HPF_SWITCH(3),
216*4882a593Smuzhiyun ADAU1977_HPF_SWITCH(4),
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun ADAU1977_DC_SUB_SWITCH(1),
219*4882a593Smuzhiyun ADAU1977_DC_SUB_SWITCH(2),
220*4882a593Smuzhiyun ADAU1977_DC_SUB_SWITCH(3),
221*4882a593Smuzhiyun ADAU1977_DC_SUB_SWITCH(4),
222*4882a593Smuzhiyun };
223*4882a593Smuzhiyun
adau1977_reset(struct adau1977 * adau1977)224*4882a593Smuzhiyun static int adau1977_reset(struct adau1977 *adau1977)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun int ret;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /*
229*4882a593Smuzhiyun * The reset bit is obviously volatile, but we need to be able to cache
230*4882a593Smuzhiyun * the other bits in the register, so we can't just mark the whole
231*4882a593Smuzhiyun * register as volatile. Since this is the only place where we'll ever
232*4882a593Smuzhiyun * touch the reset bit just bypass the cache for this operation.
233*4882a593Smuzhiyun */
234*4882a593Smuzhiyun regcache_cache_bypass(adau1977->regmap, true);
235*4882a593Smuzhiyun ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER,
236*4882a593Smuzhiyun ADAU1977_POWER_RESET);
237*4882a593Smuzhiyun regcache_cache_bypass(adau1977->regmap, false);
238*4882a593Smuzhiyun if (ret)
239*4882a593Smuzhiyun return ret;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun return ret;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /*
245*4882a593Smuzhiyun * Returns the appropriate setting for ths FS field in the CTRL0 register
246*4882a593Smuzhiyun * depending on the rate.
247*4882a593Smuzhiyun */
adau1977_lookup_fs(unsigned int rate)248*4882a593Smuzhiyun static int adau1977_lookup_fs(unsigned int rate)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun if (rate >= 8000 && rate <= 12000)
251*4882a593Smuzhiyun return ADAU1977_SAI_CTRL0_FS_8000_12000;
252*4882a593Smuzhiyun else if (rate >= 16000 && rate <= 24000)
253*4882a593Smuzhiyun return ADAU1977_SAI_CTRL0_FS_16000_24000;
254*4882a593Smuzhiyun else if (rate >= 32000 && rate <= 48000)
255*4882a593Smuzhiyun return ADAU1977_SAI_CTRL0_FS_32000_48000;
256*4882a593Smuzhiyun else if (rate >= 64000 && rate <= 96000)
257*4882a593Smuzhiyun return ADAU1977_SAI_CTRL0_FS_64000_96000;
258*4882a593Smuzhiyun else if (rate >= 128000 && rate <= 192000)
259*4882a593Smuzhiyun return ADAU1977_SAI_CTRL0_FS_128000_192000;
260*4882a593Smuzhiyun else
261*4882a593Smuzhiyun return -EINVAL;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
adau1977_lookup_mcs(struct adau1977 * adau1977,unsigned int rate,unsigned int fs)264*4882a593Smuzhiyun static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate,
265*4882a593Smuzhiyun unsigned int fs)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun unsigned int mcs;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun /*
270*4882a593Smuzhiyun * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs
271*4882a593Smuzhiyun * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs
272*4882a593Smuzhiyun * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate)
273*4882a593Smuzhiyun */
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun rate *= 512 >> fs;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if (adau1977->sysclk % rate != 0)
278*4882a593Smuzhiyun return -EINVAL;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun mcs = adau1977->sysclk / rate;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun /* The factors configured by MCS are 1, 2, 3, 4, 6 */
283*4882a593Smuzhiyun if (mcs < 1 || mcs > 6 || mcs == 5)
284*4882a593Smuzhiyun return -EINVAL;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun mcs = mcs - 1;
287*4882a593Smuzhiyun if (mcs == 5)
288*4882a593Smuzhiyun mcs = 4;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return mcs;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
adau1977_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)293*4882a593Smuzhiyun static int adau1977_hw_params(struct snd_pcm_substream *substream,
294*4882a593Smuzhiyun struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
297*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(component);
298*4882a593Smuzhiyun unsigned int rate = params_rate(params);
299*4882a593Smuzhiyun unsigned int slot_width;
300*4882a593Smuzhiyun unsigned int ctrl0, ctrl0_mask;
301*4882a593Smuzhiyun unsigned int ctrl1;
302*4882a593Smuzhiyun int mcs, fs;
303*4882a593Smuzhiyun int ret;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun fs = adau1977_lookup_fs(rate);
306*4882a593Smuzhiyun if (fs < 0)
307*4882a593Smuzhiyun return fs;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) {
310*4882a593Smuzhiyun mcs = adau1977_lookup_mcs(adau1977, rate, fs);
311*4882a593Smuzhiyun if (mcs < 0)
312*4882a593Smuzhiyun return mcs;
313*4882a593Smuzhiyun } else {
314*4882a593Smuzhiyun mcs = 0;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK;
318*4882a593Smuzhiyun ctrl0 = fs;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun if (adau1977->right_j) {
321*4882a593Smuzhiyun switch (params_width(params)) {
322*4882a593Smuzhiyun case 16:
323*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT;
324*4882a593Smuzhiyun break;
325*4882a593Smuzhiyun case 24:
326*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun default:
329*4882a593Smuzhiyun return -EINVAL;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (adau1977->master) {
335*4882a593Smuzhiyun switch (params_width(params)) {
336*4882a593Smuzhiyun case 16:
337*4882a593Smuzhiyun ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT;
338*4882a593Smuzhiyun slot_width = 16;
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun case 24:
341*4882a593Smuzhiyun case 32:
342*4882a593Smuzhiyun ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT;
343*4882a593Smuzhiyun slot_width = 32;
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun default:
346*4882a593Smuzhiyun return -EINVAL;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /* In TDM mode there is a fixed slot width */
350*4882a593Smuzhiyun if (adau1977->slot_width)
351*4882a593Smuzhiyun slot_width = adau1977->slot_width;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun if (slot_width == 16)
354*4882a593Smuzhiyun ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16;
355*4882a593Smuzhiyun else
356*4882a593Smuzhiyun ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap,
359*4882a593Smuzhiyun ADAU1977_REG_SAI_CTRL1,
360*4882a593Smuzhiyun ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK |
361*4882a593Smuzhiyun ADAU1977_SAI_CTRL1_BCLKRATE_MASK,
362*4882a593Smuzhiyun ctrl1);
363*4882a593Smuzhiyun if (ret < 0)
364*4882a593Smuzhiyun return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
368*4882a593Smuzhiyun ctrl0_mask, ctrl0);
369*4882a593Smuzhiyun if (ret < 0)
370*4882a593Smuzhiyun return ret;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL,
373*4882a593Smuzhiyun ADAU1977_PLL_MCS_MASK, mcs);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
adau1977_power_disable(struct adau1977 * adau1977)376*4882a593Smuzhiyun static int adau1977_power_disable(struct adau1977 *adau1977)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun int ret = 0;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!adau1977->enabled)
381*4882a593Smuzhiyun return 0;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
384*4882a593Smuzhiyun ADAU1977_POWER_PWUP, 0);
385*4882a593Smuzhiyun if (ret)
386*4882a593Smuzhiyun return ret;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun regcache_mark_dirty(adau1977->regmap);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun gpiod_set_value_cansleep(adau1977->reset_gpio, 0);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun regcache_cache_only(adau1977->regmap, true);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun regulator_disable(adau1977->avdd_reg);
395*4882a593Smuzhiyun if (adau1977->dvdd_reg)
396*4882a593Smuzhiyun regulator_disable(adau1977->dvdd_reg);
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun adau1977->enabled = false;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun return 0;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
adau1977_power_enable(struct adau1977 * adau1977)403*4882a593Smuzhiyun static int adau1977_power_enable(struct adau1977 *adau1977)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun unsigned int val;
406*4882a593Smuzhiyun int ret = 0;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if (adau1977->enabled)
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun ret = regulator_enable(adau1977->avdd_reg);
412*4882a593Smuzhiyun if (ret)
413*4882a593Smuzhiyun return ret;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun if (adau1977->dvdd_reg) {
416*4882a593Smuzhiyun ret = regulator_enable(adau1977->dvdd_reg);
417*4882a593Smuzhiyun if (ret)
418*4882a593Smuzhiyun goto err_disable_avdd;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun gpiod_set_value_cansleep(adau1977->reset_gpio, 1);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun regcache_cache_only(adau1977->regmap, false);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun if (adau1977->switch_mode)
426*4882a593Smuzhiyun adau1977->switch_mode(adau1977->dev);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun ret = adau1977_reset(adau1977);
429*4882a593Smuzhiyun if (ret)
430*4882a593Smuzhiyun goto err_disable_dvdd;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
433*4882a593Smuzhiyun ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP);
434*4882a593Smuzhiyun if (ret)
435*4882a593Smuzhiyun goto err_disable_dvdd;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun ret = regcache_sync(adau1977->regmap);
438*4882a593Smuzhiyun if (ret)
439*4882a593Smuzhiyun goto err_disable_dvdd;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun /*
442*4882a593Smuzhiyun * The PLL register is not affected by the software reset. It is
443*4882a593Smuzhiyun * possible that the value of the register was changed to the
444*4882a593Smuzhiyun * default value while we were in cache only mode. In this case
445*4882a593Smuzhiyun * regcache_sync will skip over it and we have to manually sync
446*4882a593Smuzhiyun * it.
447*4882a593Smuzhiyun */
448*4882a593Smuzhiyun ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val);
449*4882a593Smuzhiyun if (ret)
450*4882a593Smuzhiyun goto err_disable_dvdd;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (val == 0x41) {
453*4882a593Smuzhiyun regcache_cache_bypass(adau1977->regmap, true);
454*4882a593Smuzhiyun ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL,
455*4882a593Smuzhiyun 0x41);
456*4882a593Smuzhiyun if (ret)
457*4882a593Smuzhiyun goto err_disable_dvdd;
458*4882a593Smuzhiyun regcache_cache_bypass(adau1977->regmap, false);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun adau1977->enabled = true;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return ret;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun err_disable_dvdd:
466*4882a593Smuzhiyun if (adau1977->dvdd_reg)
467*4882a593Smuzhiyun regulator_disable(adau1977->dvdd_reg);
468*4882a593Smuzhiyun err_disable_avdd:
469*4882a593Smuzhiyun regulator_disable(adau1977->avdd_reg);
470*4882a593Smuzhiyun return ret;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
adau1977_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)473*4882a593Smuzhiyun static int adau1977_set_bias_level(struct snd_soc_component *component,
474*4882a593Smuzhiyun enum snd_soc_bias_level level)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(component);
477*4882a593Smuzhiyun int ret = 0;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun switch (level) {
480*4882a593Smuzhiyun case SND_SOC_BIAS_ON:
481*4882a593Smuzhiyun break;
482*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
483*4882a593Smuzhiyun break;
484*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
485*4882a593Smuzhiyun if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
486*4882a593Smuzhiyun ret = adau1977_power_enable(adau1977);
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
489*4882a593Smuzhiyun ret = adau1977_power_disable(adau1977);
490*4882a593Smuzhiyun break;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun return ret;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
adau1977_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int width)496*4882a593Smuzhiyun static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
497*4882a593Smuzhiyun unsigned int rx_mask, int slots, int width)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(dai->component);
500*4882a593Smuzhiyun unsigned int ctrl0, ctrl1, drv;
501*4882a593Smuzhiyun unsigned int slot[4];
502*4882a593Smuzhiyun unsigned int i;
503*4882a593Smuzhiyun int ret;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (slots == 0) {
506*4882a593Smuzhiyun /* 0 = No fixed slot width */
507*4882a593Smuzhiyun adau1977->slot_width = 0;
508*4882a593Smuzhiyun adau1977->max_master_fs = 192000;
509*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap,
510*4882a593Smuzhiyun ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK,
511*4882a593Smuzhiyun ADAU1977_SAI_CTRL0_SAI_I2S);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (rx_mask == 0 || tx_mask != 0)
515*4882a593Smuzhiyun return -EINVAL;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun drv = 0;
518*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
519*4882a593Smuzhiyun slot[i] = __ffs(rx_mask);
520*4882a593Smuzhiyun drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i);
521*4882a593Smuzhiyun rx_mask &= ~(1 << slot[i]);
522*4882a593Smuzhiyun if (slot[i] >= slots)
523*4882a593Smuzhiyun return -EINVAL;
524*4882a593Smuzhiyun if (rx_mask == 0)
525*4882a593Smuzhiyun break;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun if (rx_mask != 0)
529*4882a593Smuzhiyun return -EINVAL;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun switch (width) {
532*4882a593Smuzhiyun case 16:
533*4882a593Smuzhiyun ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16;
534*4882a593Smuzhiyun break;
535*4882a593Smuzhiyun case 24:
536*4882a593Smuzhiyun /* We can only generate 16 bit or 32 bit wide slots */
537*4882a593Smuzhiyun if (adau1977->master)
538*4882a593Smuzhiyun return -EINVAL;
539*4882a593Smuzhiyun ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24;
540*4882a593Smuzhiyun break;
541*4882a593Smuzhiyun case 32:
542*4882a593Smuzhiyun ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32;
543*4882a593Smuzhiyun break;
544*4882a593Smuzhiyun default:
545*4882a593Smuzhiyun return -EINVAL;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun switch (slots) {
549*4882a593Smuzhiyun case 2:
550*4882a593Smuzhiyun ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2;
551*4882a593Smuzhiyun break;
552*4882a593Smuzhiyun case 4:
553*4882a593Smuzhiyun ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4;
554*4882a593Smuzhiyun break;
555*4882a593Smuzhiyun case 8:
556*4882a593Smuzhiyun ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8;
557*4882a593Smuzhiyun break;
558*4882a593Smuzhiyun case 16:
559*4882a593Smuzhiyun ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16;
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun default:
562*4882a593Smuzhiyun return -EINVAL;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP,
566*4882a593Smuzhiyun ADAU1977_SAI_OVERTEMP_DRV_C(0) |
567*4882a593Smuzhiyun ADAU1977_SAI_OVERTEMP_DRV_C(1) |
568*4882a593Smuzhiyun ADAU1977_SAI_OVERTEMP_DRV_C(2) |
569*4882a593Smuzhiyun ADAU1977_SAI_OVERTEMP_DRV_C(3), drv);
570*4882a593Smuzhiyun if (ret)
571*4882a593Smuzhiyun return ret;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12,
574*4882a593Smuzhiyun (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
575*4882a593Smuzhiyun (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
576*4882a593Smuzhiyun if (ret)
577*4882a593Smuzhiyun return ret;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34,
580*4882a593Smuzhiyun (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
581*4882a593Smuzhiyun (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
582*4882a593Smuzhiyun if (ret)
583*4882a593Smuzhiyun return ret;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
586*4882a593Smuzhiyun ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0);
587*4882a593Smuzhiyun if (ret)
588*4882a593Smuzhiyun return ret;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
591*4882a593Smuzhiyun ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1);
592*4882a593Smuzhiyun if (ret)
593*4882a593Smuzhiyun return ret;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun adau1977->slot_width = width;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun /* In master mode the maximum bitclock is 24.576 MHz */
598*4882a593Smuzhiyun adau1977->max_master_fs = min(192000, 24576000 / width / slots);
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun return 0;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
adau1977_mute(struct snd_soc_dai * dai,int mute,int stream)603*4882a593Smuzhiyun static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(dai->component);
606*4882a593Smuzhiyun unsigned int val;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (mute)
609*4882a593Smuzhiyun val = ADAU1977_MISC_CONTROL_MMUTE;
610*4882a593Smuzhiyun else
611*4882a593Smuzhiyun val = 0;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL,
614*4882a593Smuzhiyun ADAU1977_MISC_CONTROL_MMUTE, val);
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
adau1977_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)617*4882a593Smuzhiyun static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(dai->component);
620*4882a593Smuzhiyun unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0;
621*4882a593Smuzhiyun bool invert_lrclk;
622*4882a593Smuzhiyun int ret;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
625*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
626*4882a593Smuzhiyun adau1977->master = false;
627*4882a593Smuzhiyun break;
628*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
629*4882a593Smuzhiyun ctrl1 |= ADAU1977_SAI_CTRL1_MASTER;
630*4882a593Smuzhiyun adau1977->master = true;
631*4882a593Smuzhiyun break;
632*4882a593Smuzhiyun default:
633*4882a593Smuzhiyun return -EINVAL;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
637*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_NF:
638*4882a593Smuzhiyun invert_lrclk = false;
639*4882a593Smuzhiyun break;
640*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_NF:
641*4882a593Smuzhiyun block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
642*4882a593Smuzhiyun invert_lrclk = false;
643*4882a593Smuzhiyun break;
644*4882a593Smuzhiyun case SND_SOC_DAIFMT_NB_IF:
645*4882a593Smuzhiyun invert_lrclk = true;
646*4882a593Smuzhiyun break;
647*4882a593Smuzhiyun case SND_SOC_DAIFMT_IB_IF:
648*4882a593Smuzhiyun block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
649*4882a593Smuzhiyun invert_lrclk = true;
650*4882a593Smuzhiyun break;
651*4882a593Smuzhiyun default:
652*4882a593Smuzhiyun return -EINVAL;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun adau1977->right_j = false;
656*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
657*4882a593Smuzhiyun case SND_SOC_DAIFMT_I2S:
658*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
659*4882a593Smuzhiyun break;
660*4882a593Smuzhiyun case SND_SOC_DAIFMT_LEFT_J:
661*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
662*4882a593Smuzhiyun invert_lrclk = !invert_lrclk;
663*4882a593Smuzhiyun break;
664*4882a593Smuzhiyun case SND_SOC_DAIFMT_RIGHT_J:
665*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
666*4882a593Smuzhiyun adau1977->right_j = true;
667*4882a593Smuzhiyun invert_lrclk = !invert_lrclk;
668*4882a593Smuzhiyun break;
669*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_A:
670*4882a593Smuzhiyun ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
671*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
672*4882a593Smuzhiyun invert_lrclk = false;
673*4882a593Smuzhiyun break;
674*4882a593Smuzhiyun case SND_SOC_DAIFMT_DSP_B:
675*4882a593Smuzhiyun ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
676*4882a593Smuzhiyun ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
677*4882a593Smuzhiyun invert_lrclk = false;
678*4882a593Smuzhiyun break;
679*4882a593Smuzhiyun default:
680*4882a593Smuzhiyun return -EINVAL;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (invert_lrclk)
684*4882a593Smuzhiyun block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
687*4882a593Smuzhiyun ADAU1977_BLOCK_POWER_SAI_LR_POL |
688*4882a593Smuzhiyun ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power);
689*4882a593Smuzhiyun if (ret)
690*4882a593Smuzhiyun return ret;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
693*4882a593Smuzhiyun ADAU1977_SAI_CTRL0_FMT_MASK,
694*4882a593Smuzhiyun ctrl0);
695*4882a593Smuzhiyun if (ret)
696*4882a593Smuzhiyun return ret;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
699*4882a593Smuzhiyun ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE,
700*4882a593Smuzhiyun ctrl1);
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun
adau1977_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)703*4882a593Smuzhiyun static int adau1977_startup(struct snd_pcm_substream *substream,
704*4882a593Smuzhiyun struct snd_soc_dai *dai)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(dai->component);
707*4882a593Smuzhiyun u64 formats = 0;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (adau1977->slot_width == 16)
710*4882a593Smuzhiyun formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE;
711*4882a593Smuzhiyun else if (adau1977->right_j || adau1977->slot_width == 24)
712*4882a593Smuzhiyun formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
713*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun snd_pcm_hw_constraint_list(substream->runtime, 0,
716*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (adau1977->master)
719*4882a593Smuzhiyun snd_pcm_hw_constraint_minmax(substream->runtime,
720*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun if (formats != 0)
723*4882a593Smuzhiyun snd_pcm_hw_constraint_mask64(substream->runtime,
724*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_FORMAT, formats);
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun return 0;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
adau1977_set_tristate(struct snd_soc_dai * dai,int tristate)729*4882a593Smuzhiyun static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(dai->component);
732*4882a593Smuzhiyun unsigned int val;
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun if (tristate)
735*4882a593Smuzhiyun val = ADAU1977_SAI_OVERTEMP_DRV_HIZ;
736*4882a593Smuzhiyun else
737*4882a593Smuzhiyun val = 0;
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP,
740*4882a593Smuzhiyun ADAU1977_SAI_OVERTEMP_DRV_HIZ, val);
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun static const struct snd_soc_dai_ops adau1977_dai_ops = {
744*4882a593Smuzhiyun .startup = adau1977_startup,
745*4882a593Smuzhiyun .hw_params = adau1977_hw_params,
746*4882a593Smuzhiyun .mute_stream = adau1977_mute,
747*4882a593Smuzhiyun .set_fmt = adau1977_set_dai_fmt,
748*4882a593Smuzhiyun .set_tdm_slot = adau1977_set_tdm_slot,
749*4882a593Smuzhiyun .set_tristate = adau1977_set_tristate,
750*4882a593Smuzhiyun };
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun static struct snd_soc_dai_driver adau1977_dai = {
753*4882a593Smuzhiyun .name = "adau1977-hifi",
754*4882a593Smuzhiyun .capture = {
755*4882a593Smuzhiyun .stream_name = "Capture",
756*4882a593Smuzhiyun .channels_min = 1,
757*4882a593Smuzhiyun .channels_max = 4,
758*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_KNOT,
759*4882a593Smuzhiyun .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
760*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE,
761*4882a593Smuzhiyun .sig_bits = 24,
762*4882a593Smuzhiyun },
763*4882a593Smuzhiyun .ops = &adau1977_dai_ops,
764*4882a593Smuzhiyun };
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun static const unsigned int adau1977_rates[] = {
767*4882a593Smuzhiyun 8000, 16000, 32000, 64000, 128000,
768*4882a593Smuzhiyun 11025, 22050, 44100, 88200, 172400,
769*4882a593Smuzhiyun 12000, 24000, 48000, 96000, 192000,
770*4882a593Smuzhiyun };
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun #define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f
773*4882a593Smuzhiyun #define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0
774*4882a593Smuzhiyun #define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00
775*4882a593Smuzhiyun /* All rates >= 32000 */
776*4882a593Smuzhiyun #define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c
777*4882a593Smuzhiyun
adau1977_check_sysclk(unsigned int mclk,unsigned int base_freq)778*4882a593Smuzhiyun static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun unsigned int mcs;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun if (mclk % (base_freq * 128) != 0)
783*4882a593Smuzhiyun return false;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun mcs = mclk / (128 * base_freq);
786*4882a593Smuzhiyun if (mcs < 1 || mcs > 6 || mcs == 5)
787*4882a593Smuzhiyun return false;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun return true;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
adau1977_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)792*4882a593Smuzhiyun static int adau1977_set_sysclk(struct snd_soc_component *component,
793*4882a593Smuzhiyun int clk_id, int source, unsigned int freq, int dir)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(component);
796*4882a593Smuzhiyun unsigned int mask = 0;
797*4882a593Smuzhiyun unsigned int clk_src;
798*4882a593Smuzhiyun unsigned int ret;
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun if (dir != SND_SOC_CLOCK_IN)
801*4882a593Smuzhiyun return -EINVAL;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun if (clk_id != ADAU1977_SYSCLK)
804*4882a593Smuzhiyun return -EINVAL;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun switch (source) {
807*4882a593Smuzhiyun case ADAU1977_SYSCLK_SRC_MCLK:
808*4882a593Smuzhiyun clk_src = 0;
809*4882a593Smuzhiyun break;
810*4882a593Smuzhiyun case ADAU1977_SYSCLK_SRC_LRCLK:
811*4882a593Smuzhiyun clk_src = ADAU1977_PLL_CLK_S;
812*4882a593Smuzhiyun break;
813*4882a593Smuzhiyun default:
814*4882a593Smuzhiyun return -EINVAL;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) {
818*4882a593Smuzhiyun if (freq < 4000000 || freq > 36864000)
819*4882a593Smuzhiyun return -EINVAL;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun if (adau1977_check_sysclk(freq, 32000))
822*4882a593Smuzhiyun mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000;
823*4882a593Smuzhiyun if (adau1977_check_sysclk(freq, 44100))
824*4882a593Smuzhiyun mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100;
825*4882a593Smuzhiyun if (adau1977_check_sysclk(freq, 48000))
826*4882a593Smuzhiyun mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun if (mask == 0)
829*4882a593Smuzhiyun return -EINVAL;
830*4882a593Smuzhiyun } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) {
831*4882a593Smuzhiyun mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL,
835*4882a593Smuzhiyun ADAU1977_PLL_CLK_S, clk_src);
836*4882a593Smuzhiyun if (ret)
837*4882a593Smuzhiyun return ret;
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun adau1977->constraints.mask = mask;
840*4882a593Smuzhiyun adau1977->sysclk_src = source;
841*4882a593Smuzhiyun adau1977->sysclk = freq;
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun return 0;
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun
adau1977_component_probe(struct snd_soc_component * component)846*4882a593Smuzhiyun static int adau1977_component_probe(struct snd_soc_component *component)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
849*4882a593Smuzhiyun struct adau1977 *adau1977 = snd_soc_component_get_drvdata(component);
850*4882a593Smuzhiyun int ret;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun switch (adau1977->type) {
853*4882a593Smuzhiyun case ADAU1977:
854*4882a593Smuzhiyun ret = snd_soc_dapm_new_controls(dapm,
855*4882a593Smuzhiyun adau1977_micbias_dapm_widgets,
856*4882a593Smuzhiyun ARRAY_SIZE(adau1977_micbias_dapm_widgets));
857*4882a593Smuzhiyun if (ret < 0)
858*4882a593Smuzhiyun return ret;
859*4882a593Smuzhiyun break;
860*4882a593Smuzhiyun default:
861*4882a593Smuzhiyun break;
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun return 0;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun static const struct snd_soc_component_driver adau1977_component_driver = {
868*4882a593Smuzhiyun .probe = adau1977_component_probe,
869*4882a593Smuzhiyun .set_bias_level = adau1977_set_bias_level,
870*4882a593Smuzhiyun .set_sysclk = adau1977_set_sysclk,
871*4882a593Smuzhiyun .controls = adau1977_snd_controls,
872*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(adau1977_snd_controls),
873*4882a593Smuzhiyun .dapm_widgets = adau1977_dapm_widgets,
874*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets),
875*4882a593Smuzhiyun .dapm_routes = adau1977_dapm_routes,
876*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes),
877*4882a593Smuzhiyun .use_pmdown_time = 1,
878*4882a593Smuzhiyun .endianness = 1,
879*4882a593Smuzhiyun .non_legacy_dai_naming = 1,
880*4882a593Smuzhiyun };
881*4882a593Smuzhiyun
adau1977_setup_micbias(struct adau1977 * adau1977)882*4882a593Smuzhiyun static int adau1977_setup_micbias(struct adau1977 *adau1977)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun struct adau1977_platform_data *pdata = adau1977->dev->platform_data;
885*4882a593Smuzhiyun unsigned int micbias;
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun if (pdata)
888*4882a593Smuzhiyun micbias = pdata->micbias;
889*4882a593Smuzhiyun else if (device_property_read_u32(adau1977->dev, "adi,micbias",
890*4882a593Smuzhiyun &micbias))
891*4882a593Smuzhiyun micbias = ADAU1977_MICBIAS_8V5;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun if (micbias > ADAU1977_MICBIAS_9V0) {
894*4882a593Smuzhiyun dev_err(adau1977->dev, "Invalid value for 'adi,micbias'\n");
895*4882a593Smuzhiyun return -EINVAL;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS,
899*4882a593Smuzhiyun ADAU1977_MICBIAS_MB_VOLTS_MASK,
900*4882a593Smuzhiyun micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET);
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun
adau1977_probe(struct device * dev,struct regmap * regmap,enum adau1977_type type,void (* switch_mode)(struct device * dev))903*4882a593Smuzhiyun int adau1977_probe(struct device *dev, struct regmap *regmap,
904*4882a593Smuzhiyun enum adau1977_type type, void (*switch_mode)(struct device *dev))
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun unsigned int power_off_mask;
907*4882a593Smuzhiyun struct adau1977 *adau1977;
908*4882a593Smuzhiyun int ret;
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun if (IS_ERR(regmap))
911*4882a593Smuzhiyun return PTR_ERR(regmap);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL);
914*4882a593Smuzhiyun if (adau1977 == NULL)
915*4882a593Smuzhiyun return -ENOMEM;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun adau1977->dev = dev;
918*4882a593Smuzhiyun adau1977->type = type;
919*4882a593Smuzhiyun adau1977->regmap = regmap;
920*4882a593Smuzhiyun adau1977->switch_mode = switch_mode;
921*4882a593Smuzhiyun adau1977->max_master_fs = 192000;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun adau1977->constraints.list = adau1977_rates;
924*4882a593Smuzhiyun adau1977->constraints.count = ARRAY_SIZE(adau1977_rates);
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun adau1977->avdd_reg = devm_regulator_get(dev, "AVDD");
927*4882a593Smuzhiyun if (IS_ERR(adau1977->avdd_reg))
928*4882a593Smuzhiyun return PTR_ERR(adau1977->avdd_reg);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD");
931*4882a593Smuzhiyun if (IS_ERR(adau1977->dvdd_reg)) {
932*4882a593Smuzhiyun if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV)
933*4882a593Smuzhiyun return PTR_ERR(adau1977->dvdd_reg);
934*4882a593Smuzhiyun adau1977->dvdd_reg = NULL;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun adau1977->reset_gpio = devm_gpiod_get_optional(dev, "reset",
938*4882a593Smuzhiyun GPIOD_OUT_LOW);
939*4882a593Smuzhiyun if (IS_ERR(adau1977->reset_gpio))
940*4882a593Smuzhiyun return PTR_ERR(adau1977->reset_gpio);
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun dev_set_drvdata(dev, adau1977);
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun if (adau1977->reset_gpio)
945*4882a593Smuzhiyun ndelay(100);
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun ret = adau1977_power_enable(adau1977);
948*4882a593Smuzhiyun if (ret)
949*4882a593Smuzhiyun return ret;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun if (type == ADAU1977) {
952*4882a593Smuzhiyun ret = adau1977_setup_micbias(adau1977);
953*4882a593Smuzhiyun if (ret)
954*4882a593Smuzhiyun goto err_poweroff;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (adau1977->dvdd_reg)
958*4882a593Smuzhiyun power_off_mask = ~0;
959*4882a593Smuzhiyun else
960*4882a593Smuzhiyun power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
963*4882a593Smuzhiyun power_off_mask, 0x00);
964*4882a593Smuzhiyun if (ret)
965*4882a593Smuzhiyun goto err_poweroff;
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun ret = adau1977_power_disable(adau1977);
968*4882a593Smuzhiyun if (ret)
969*4882a593Smuzhiyun return ret;
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun return devm_snd_soc_register_component(dev, &adau1977_component_driver,
972*4882a593Smuzhiyun &adau1977_dai, 1);
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun err_poweroff:
975*4882a593Smuzhiyun adau1977_power_disable(adau1977);
976*4882a593Smuzhiyun return ret;
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adau1977_probe);
980*4882a593Smuzhiyun
adau1977_register_volatile(struct device * dev,unsigned int reg)981*4882a593Smuzhiyun static bool adau1977_register_volatile(struct device *dev, unsigned int reg)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun switch (reg) {
984*4882a593Smuzhiyun case ADAU1977_REG_STATUS(0):
985*4882a593Smuzhiyun case ADAU1977_REG_STATUS(1):
986*4882a593Smuzhiyun case ADAU1977_REG_STATUS(2):
987*4882a593Smuzhiyun case ADAU1977_REG_STATUS(3):
988*4882a593Smuzhiyun case ADAU1977_REG_ADC_CLIP:
989*4882a593Smuzhiyun return true;
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun return false;
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun const struct regmap_config adau1977_regmap_config = {
996*4882a593Smuzhiyun .max_register = ADAU1977_REG_DC_HPF_CAL,
997*4882a593Smuzhiyun .volatile_reg = adau1977_register_volatile,
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
1000*4882a593Smuzhiyun .reg_defaults = adau1977_reg_defaults,
1001*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults),
1002*4882a593Smuzhiyun };
1003*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adau1977_regmap_config);
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver");
1006*4882a593Smuzhiyun MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
1007*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1008