xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/tas2562.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Driver for the Texas Instruments TAS2562 CODEC
4*4882a593Smuzhiyun // Copyright (C) 2019 Texas Instruments Inc.
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/errno.h>
9*4882a593Smuzhiyun #include <linux/device.h>
10*4882a593Smuzhiyun #include <linux/i2c.h>
11*4882a593Smuzhiyun #include <linux/pm_runtime.h>
12*4882a593Smuzhiyun #include <linux/regmap.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
15*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <sound/pcm.h>
19*4882a593Smuzhiyun #include <sound/pcm_params.h>
20*4882a593Smuzhiyun #include <sound/soc.h>
21*4882a593Smuzhiyun #include <sound/soc-dapm.h>
22*4882a593Smuzhiyun #include <sound/tlv.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "tas2562.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
27*4882a593Smuzhiyun 			 SNDRV_PCM_FORMAT_S32_LE)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* DVC equation involves floating point math
30*4882a593Smuzhiyun  * round(10^(volume in dB/20)*2^30)
31*4882a593Smuzhiyun  * so create a lookup table for 2dB step
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun static const unsigned int float_vol_db_lookup[] = {
34*4882a593Smuzhiyun 0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151,
35*4882a593Smuzhiyun 0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b,
36*4882a593Smuzhiyun 0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
37*4882a593Smuzhiyun 0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f,
38*4882a593Smuzhiyun 0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7,
39*4882a593Smuzhiyun 0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d,
40*4882a593Smuzhiyun 0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a,
41*4882a593Smuzhiyun 0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27,
42*4882a593Smuzhiyun 0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68,
43*4882a593Smuzhiyun 0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362,
44*4882a593Smuzhiyun 0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun struct tas2562_data {
48*4882a593Smuzhiyun 	struct snd_soc_component *component;
49*4882a593Smuzhiyun 	struct gpio_desc *sdz_gpio;
50*4882a593Smuzhiyun 	struct regmap *regmap;
51*4882a593Smuzhiyun 	struct device *dev;
52*4882a593Smuzhiyun 	struct i2c_client *client;
53*4882a593Smuzhiyun 	int v_sense_slot;
54*4882a593Smuzhiyun 	int i_sense_slot;
55*4882a593Smuzhiyun 	int volume_lvl;
56*4882a593Smuzhiyun 	int model_id;
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun enum tas256x_model {
60*4882a593Smuzhiyun 	TAS2562,
61*4882a593Smuzhiyun 	TAS2563,
62*4882a593Smuzhiyun 	TAS2564,
63*4882a593Smuzhiyun 	TAS2110,
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
tas2562_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)66*4882a593Smuzhiyun static int tas2562_set_bias_level(struct snd_soc_component *component,
67*4882a593Smuzhiyun 				 enum snd_soc_bias_level level)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	struct tas2562_data *tas2562 =
70*4882a593Smuzhiyun 			snd_soc_component_get_drvdata(component);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	switch (level) {
73*4882a593Smuzhiyun 	case SND_SOC_BIAS_ON:
74*4882a593Smuzhiyun 		snd_soc_component_update_bits(component,
75*4882a593Smuzhiyun 			TAS2562_PWR_CTRL,
76*4882a593Smuzhiyun 			TAS2562_MODE_MASK, TAS2562_ACTIVE);
77*4882a593Smuzhiyun 		break;
78*4882a593Smuzhiyun 	case SND_SOC_BIAS_STANDBY:
79*4882a593Smuzhiyun 	case SND_SOC_BIAS_PREPARE:
80*4882a593Smuzhiyun 		snd_soc_component_update_bits(component,
81*4882a593Smuzhiyun 			TAS2562_PWR_CTRL,
82*4882a593Smuzhiyun 			TAS2562_MODE_MASK, TAS2562_MUTE);
83*4882a593Smuzhiyun 		break;
84*4882a593Smuzhiyun 	case SND_SOC_BIAS_OFF:
85*4882a593Smuzhiyun 		snd_soc_component_update_bits(component,
86*4882a593Smuzhiyun 			TAS2562_PWR_CTRL,
87*4882a593Smuzhiyun 			TAS2562_MODE_MASK, TAS2562_SHUTDOWN);
88*4882a593Smuzhiyun 		break;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	default:
91*4882a593Smuzhiyun 		dev_err(tas2562->dev,
92*4882a593Smuzhiyun 				"wrong power level setting %d\n", level);
93*4882a593Smuzhiyun 		return -EINVAL;
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	return 0;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
tas2562_set_samplerate(struct tas2562_data * tas2562,int samplerate)99*4882a593Smuzhiyun static int tas2562_set_samplerate(struct tas2562_data *tas2562, int samplerate)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	int samp_rate;
102*4882a593Smuzhiyun 	int ramp_rate;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	switch (samplerate) {
105*4882a593Smuzhiyun 	case 7350:
106*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
107*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
108*4882a593Smuzhiyun 		break;
109*4882a593Smuzhiyun 	case 8000:
110*4882a593Smuzhiyun 		ramp_rate = 0;
111*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
112*4882a593Smuzhiyun 		break;
113*4882a593Smuzhiyun 	case 14700:
114*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
115*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case 16000:
118*4882a593Smuzhiyun 		ramp_rate = 0;
119*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case 22050:
122*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
123*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
124*4882a593Smuzhiyun 		break;
125*4882a593Smuzhiyun 	case 24000:
126*4882a593Smuzhiyun 		ramp_rate = 0;
127*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
128*4882a593Smuzhiyun 		break;
129*4882a593Smuzhiyun 	case 29400:
130*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
131*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun 	case 32000:
134*4882a593Smuzhiyun 		ramp_rate = 0;
135*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
136*4882a593Smuzhiyun 		break;
137*4882a593Smuzhiyun 	case 44100:
138*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
139*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
140*4882a593Smuzhiyun 		break;
141*4882a593Smuzhiyun 	case 48000:
142*4882a593Smuzhiyun 		ramp_rate = 0;
143*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
144*4882a593Smuzhiyun 		break;
145*4882a593Smuzhiyun 	case 88200:
146*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
147*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
148*4882a593Smuzhiyun 		break;
149*4882a593Smuzhiyun 	case 96000:
150*4882a593Smuzhiyun 		ramp_rate = 0;
151*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
152*4882a593Smuzhiyun 		break;
153*4882a593Smuzhiyun 	case 176400:
154*4882a593Smuzhiyun 		ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
155*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
156*4882a593Smuzhiyun 		break;
157*4882a593Smuzhiyun 	case 192000:
158*4882a593Smuzhiyun 		ramp_rate = 0;
159*4882a593Smuzhiyun 		samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
160*4882a593Smuzhiyun 		break;
161*4882a593Smuzhiyun 	default:
162*4882a593Smuzhiyun 		dev_info(tas2562->dev, "%s, unsupported sample rate, %d\n",
163*4882a593Smuzhiyun 			__func__, samplerate);
164*4882a593Smuzhiyun 		return -EINVAL;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
168*4882a593Smuzhiyun 		TAS2562_TDM_CFG0_RAMPRATE_MASK,	ramp_rate);
169*4882a593Smuzhiyun 	snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
170*4882a593Smuzhiyun 		TAS2562_TDM_CFG0_SAMPRATE_MASK,	samp_rate);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
tas2562_set_dai_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)175*4882a593Smuzhiyun static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
176*4882a593Smuzhiyun 		unsigned int tx_mask, unsigned int rx_mask,
177*4882a593Smuzhiyun 		int slots, int slot_width)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
180*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
181*4882a593Smuzhiyun 	int left_slot, right_slot;
182*4882a593Smuzhiyun 	int slots_cfg;
183*4882a593Smuzhiyun 	int ret;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (!tx_mask) {
186*4882a593Smuzhiyun 		dev_err(component->dev, "tx masks must not be 0\n");
187*4882a593Smuzhiyun 		return -EINVAL;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (slots == 1) {
191*4882a593Smuzhiyun 		if (tx_mask != 1)
192*4882a593Smuzhiyun 			return -EINVAL;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 		left_slot = 0;
195*4882a593Smuzhiyun 		right_slot = 0;
196*4882a593Smuzhiyun 	} else {
197*4882a593Smuzhiyun 		left_slot = __ffs(tx_mask);
198*4882a593Smuzhiyun 		tx_mask &= ~(1 << left_slot);
199*4882a593Smuzhiyun 		if (tx_mask == 0) {
200*4882a593Smuzhiyun 			right_slot = left_slot;
201*4882a593Smuzhiyun 		} else {
202*4882a593Smuzhiyun 			right_slot = __ffs(tx_mask);
203*4882a593Smuzhiyun 			tx_mask &= ~(1 << right_slot);
204*4882a593Smuzhiyun 		}
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg);
210*4882a593Smuzhiyun 	if (ret < 0)
211*4882a593Smuzhiyun 		return ret;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	switch (slot_width) {
214*4882a593Smuzhiyun 	case 16:
215*4882a593Smuzhiyun 		ret = snd_soc_component_update_bits(component,
216*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2,
217*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_MASK,
218*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_16B);
219*4882a593Smuzhiyun 		break;
220*4882a593Smuzhiyun 	case 24:
221*4882a593Smuzhiyun 		ret = snd_soc_component_update_bits(component,
222*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2,
223*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_MASK,
224*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_24B);
225*4882a593Smuzhiyun 		break;
226*4882a593Smuzhiyun 	case 32:
227*4882a593Smuzhiyun 		ret = snd_soc_component_update_bits(component,
228*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2,
229*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_MASK,
230*4882a593Smuzhiyun 						    TAS2562_TDM_CFG2_RXLEN_32B);
231*4882a593Smuzhiyun 		break;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	case 0:
234*4882a593Smuzhiyun 		/* Do not change slot width */
235*4882a593Smuzhiyun 		break;
236*4882a593Smuzhiyun 	default:
237*4882a593Smuzhiyun 		dev_err(tas2562->dev, "slot width not supported");
238*4882a593Smuzhiyun 		ret = -EINVAL;
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	if (ret < 0)
242*4882a593Smuzhiyun 		return ret;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5,
245*4882a593Smuzhiyun 					    TAS2562_TDM_CFG5_VSNS_SLOT_MASK,
246*4882a593Smuzhiyun 					    tas2562->v_sense_slot);
247*4882a593Smuzhiyun 	if (ret < 0)
248*4882a593Smuzhiyun 		return ret;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6,
251*4882a593Smuzhiyun 					    TAS2562_TDM_CFG6_ISNS_SLOT_MASK,
252*4882a593Smuzhiyun 					    tas2562->i_sense_slot);
253*4882a593Smuzhiyun 	if (ret < 0)
254*4882a593Smuzhiyun 		return ret;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
tas2562_set_bitwidth(struct tas2562_data * tas2562,int bitwidth)259*4882a593Smuzhiyun static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	int ret;
262*4882a593Smuzhiyun 	int val;
263*4882a593Smuzhiyun 	int sense_en;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	switch (bitwidth) {
266*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S16_LE:
267*4882a593Smuzhiyun 		snd_soc_component_update_bits(tas2562->component,
268*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2,
269*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_MASK,
270*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_16B);
271*4882a593Smuzhiyun 		break;
272*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_LE:
273*4882a593Smuzhiyun 		snd_soc_component_update_bits(tas2562->component,
274*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2,
275*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_MASK,
276*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_24B);
277*4882a593Smuzhiyun 		break;
278*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S32_LE:
279*4882a593Smuzhiyun 		snd_soc_component_update_bits(tas2562->component,
280*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2,
281*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_MASK,
282*4882a593Smuzhiyun 					      TAS2562_TDM_CFG2_RXWLEN_32B);
283*4882a593Smuzhiyun 		break;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	default:
286*4882a593Smuzhiyun 		dev_info(tas2562->dev, "Unsupported bitwidth format\n");
287*4882a593Smuzhiyun 		return -EINVAL;
288*4882a593Smuzhiyun 	}
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL);
291*4882a593Smuzhiyun 	if (val < 0)
292*4882a593Smuzhiyun 		return val;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	if (val & (1 << TAS2562_VSENSE_POWER_EN))
295*4882a593Smuzhiyun 		sense_en = 0;
296*4882a593Smuzhiyun 	else
297*4882a593Smuzhiyun 		sense_en = TAS2562_TDM_CFG5_VSNS_EN;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5,
300*4882a593Smuzhiyun 		TAS2562_TDM_CFG5_VSNS_EN, sense_en);
301*4882a593Smuzhiyun 	if (ret < 0)
302*4882a593Smuzhiyun 		return ret;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	if (val & (1 << TAS2562_ISENSE_POWER_EN))
305*4882a593Smuzhiyun 		sense_en = 0;
306*4882a593Smuzhiyun 	else
307*4882a593Smuzhiyun 		sense_en = TAS2562_TDM_CFG6_ISNS_EN;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6,
310*4882a593Smuzhiyun 		TAS2562_TDM_CFG6_ISNS_EN, sense_en);
311*4882a593Smuzhiyun 	if (ret < 0)
312*4882a593Smuzhiyun 		return ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	return 0;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
tas2562_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)317*4882a593Smuzhiyun static int tas2562_hw_params(struct snd_pcm_substream *substream,
318*4882a593Smuzhiyun 			     struct snd_pcm_hw_params *params,
319*4882a593Smuzhiyun 			     struct snd_soc_dai *dai)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
322*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
323*4882a593Smuzhiyun 	int ret;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	ret = tas2562_set_bitwidth(tas2562, params_format(params));
326*4882a593Smuzhiyun 	if (ret) {
327*4882a593Smuzhiyun 		dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
328*4882a593Smuzhiyun 		return ret;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	ret = tas2562_set_samplerate(tas2562, params_rate(params));
332*4882a593Smuzhiyun 	if (ret)
333*4882a593Smuzhiyun 		dev_err(tas2562->dev, "set sample rate failed, %d\n", ret);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	return ret;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
tas2562_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)338*4882a593Smuzhiyun static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
341*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
342*4882a593Smuzhiyun 	u8 asi_cfg_1 = 0;
343*4882a593Smuzhiyun 	u8 tdm_rx_start_slot = 0;
344*4882a593Smuzhiyun 	int ret;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
347*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_NB_NF:
348*4882a593Smuzhiyun 		asi_cfg_1 = 0;
349*4882a593Smuzhiyun 		break;
350*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_IB_NF:
351*4882a593Smuzhiyun 		asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING;
352*4882a593Smuzhiyun 		break;
353*4882a593Smuzhiyun 	default:
354*4882a593Smuzhiyun 		dev_err(tas2562->dev, "ASI format Inverse is not found\n");
355*4882a593Smuzhiyun 		return -EINVAL;
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
359*4882a593Smuzhiyun 					    TAS2562_TDM_CFG1_RX_EDGE_MASK,
360*4882a593Smuzhiyun 					    asi_cfg_1);
361*4882a593Smuzhiyun 	if (ret < 0) {
362*4882a593Smuzhiyun 		dev_err(tas2562->dev, "Failed to set RX edge\n");
363*4882a593Smuzhiyun 		return ret;
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
366*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_LEFT_J:
367*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_DSP_B:
368*4882a593Smuzhiyun 		tdm_rx_start_slot = 0;
369*4882a593Smuzhiyun 		break;
370*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_I2S:
371*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_DSP_A:
372*4882a593Smuzhiyun 		tdm_rx_start_slot = 1;
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 	default:
375*4882a593Smuzhiyun 		dev_err(tas2562->dev,
376*4882a593Smuzhiyun 			"DAI Format is not found, fmt=0x%x\n", fmt);
377*4882a593Smuzhiyun 		return -EINVAL;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
381*4882a593Smuzhiyun 				TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1));
382*4882a593Smuzhiyun 	if (ret < 0)
383*4882a593Smuzhiyun 		return ret;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	return 0;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
tas2562_mute(struct snd_soc_dai * dai,int mute,int direction)388*4882a593Smuzhiyun static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
393*4882a593Smuzhiyun 					     TAS2562_MODE_MASK,
394*4882a593Smuzhiyun 					     mute ? TAS2562_MUTE : 0);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
tas2562_codec_probe(struct snd_soc_component * component)397*4882a593Smuzhiyun static int tas2562_codec_probe(struct snd_soc_component *component)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
400*4882a593Smuzhiyun 	int ret;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	tas2562->component = component;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (tas2562->sdz_gpio)
405*4882a593Smuzhiyun 		gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
408*4882a593Smuzhiyun 					    TAS2562_MODE_MASK, TAS2562_MUTE);
409*4882a593Smuzhiyun 	if (ret < 0)
410*4882a593Smuzhiyun 		return ret;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	return 0;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun #ifdef CONFIG_PM
tas2562_suspend(struct snd_soc_component * component)416*4882a593Smuzhiyun static int tas2562_suspend(struct snd_soc_component *component)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	regcache_cache_only(tas2562->regmap, true);
421*4882a593Smuzhiyun 	regcache_mark_dirty(tas2562->regmap);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	if (tas2562->sdz_gpio)
424*4882a593Smuzhiyun 		gpiod_set_value_cansleep(tas2562->sdz_gpio, 0);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	return 0;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
tas2562_resume(struct snd_soc_component * component)429*4882a593Smuzhiyun static int tas2562_resume(struct snd_soc_component *component)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	if (tas2562->sdz_gpio)
434*4882a593Smuzhiyun 		gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	regcache_cache_only(tas2562->regmap, false);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	return regcache_sync(tas2562->regmap);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun #else
441*4882a593Smuzhiyun #define tas2562_suspend NULL
442*4882a593Smuzhiyun #define tas2562_resume NULL
443*4882a593Smuzhiyun #endif
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun static const char * const tas2562_ASI1_src[] = {
446*4882a593Smuzhiyun 	"I2C offset", "Left", "Right", "LeftRightDiv2",
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4,
450*4882a593Smuzhiyun 			    tas2562_ASI1_src);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun static const struct snd_kcontrol_new tas2562_asi1_mux =
453*4882a593Smuzhiyun 	SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum);
454*4882a593Smuzhiyun 
tas2562_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)455*4882a593Smuzhiyun static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
456*4882a593Smuzhiyun 			     struct snd_kcontrol *kcontrol, int event)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	struct snd_soc_component *component =
459*4882a593Smuzhiyun 					snd_soc_dapm_to_component(w->dapm);
460*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
461*4882a593Smuzhiyun 	int ret;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	switch (event) {
464*4882a593Smuzhiyun 	case SND_SOC_DAPM_POST_PMU:
465*4882a593Smuzhiyun 		ret = snd_soc_component_update_bits(component,
466*4882a593Smuzhiyun 			TAS2562_PWR_CTRL,
467*4882a593Smuzhiyun 			TAS2562_MODE_MASK,
468*4882a593Smuzhiyun 			TAS2562_MUTE);
469*4882a593Smuzhiyun 		if (ret)
470*4882a593Smuzhiyun 			goto end;
471*4882a593Smuzhiyun 		break;
472*4882a593Smuzhiyun 	case SND_SOC_DAPM_PRE_PMD:
473*4882a593Smuzhiyun 		ret = snd_soc_component_update_bits(component,
474*4882a593Smuzhiyun 			TAS2562_PWR_CTRL,
475*4882a593Smuzhiyun 			TAS2562_MODE_MASK,
476*4882a593Smuzhiyun 			TAS2562_SHUTDOWN);
477*4882a593Smuzhiyun 		if (ret)
478*4882a593Smuzhiyun 			goto end;
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 	default:
481*4882a593Smuzhiyun 		dev_err(tas2562->dev, "Not supported evevt\n");
482*4882a593Smuzhiyun 		return -EINVAL;
483*4882a593Smuzhiyun 	}
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun end:
486*4882a593Smuzhiyun 	if (ret < 0)
487*4882a593Smuzhiyun 		return ret;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	return 0;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
tas2562_volume_control_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)492*4882a593Smuzhiyun static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol,
493*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
496*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = tas2562->volume_lvl;
499*4882a593Smuzhiyun 	return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
tas2562_volume_control_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)502*4882a593Smuzhiyun static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
503*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
506*4882a593Smuzhiyun 	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
507*4882a593Smuzhiyun 	int ret;
508*4882a593Smuzhiyun 	u32 reg_val;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
511*4882a593Smuzhiyun 	ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
512*4882a593Smuzhiyun 				      (reg_val & 0xff));
513*4882a593Smuzhiyun 	if (ret)
514*4882a593Smuzhiyun 		return ret;
515*4882a593Smuzhiyun 	ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
516*4882a593Smuzhiyun 				      ((reg_val >> 8) & 0xff));
517*4882a593Smuzhiyun 	if (ret)
518*4882a593Smuzhiyun 		return ret;
519*4882a593Smuzhiyun 	ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
520*4882a593Smuzhiyun 				      ((reg_val >> 16) & 0xff));
521*4882a593Smuzhiyun 	if (ret)
522*4882a593Smuzhiyun 		return ret;
523*4882a593Smuzhiyun 	ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
524*4882a593Smuzhiyun 				      ((reg_val >> 24) & 0xff));
525*4882a593Smuzhiyun 	if (ret)
526*4882a593Smuzhiyun 		return ret;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	tas2562->volume_lvl = ucontrol->value.integer.value[0];
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	return ret;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun /* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */
534*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun static const struct snd_kcontrol_new isense_switch =
539*4882a593Smuzhiyun 	SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN,
540*4882a593Smuzhiyun 			1, 1);
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun static const struct snd_kcontrol_new vsense_switch =
543*4882a593Smuzhiyun 	SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN,
544*4882a593Smuzhiyun 			1, 1);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static const struct snd_kcontrol_new tas2562_snd_controls[] = {
547*4882a593Smuzhiyun 	SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0,
548*4882a593Smuzhiyun 		       tas2562_dac_tlv),
549*4882a593Smuzhiyun 	{
550*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
551*4882a593Smuzhiyun 		.name = "Digital Volume Control",
552*4882a593Smuzhiyun 		.index = 0,
553*4882a593Smuzhiyun 		.tlv.p = dvc_tlv,
554*4882a593Smuzhiyun 		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
555*4882a593Smuzhiyun 		.info = snd_soc_info_volsw,
556*4882a593Smuzhiyun 		.get = tas2562_volume_control_get,
557*4882a593Smuzhiyun 		.put = tas2562_volume_control_put,
558*4882a593Smuzhiyun 		.private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0),
559*4882a593Smuzhiyun 	},
560*4882a593Smuzhiyun };
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun static const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = {
563*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
564*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
565*4882a593Smuzhiyun 	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
566*4882a593Smuzhiyun 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
567*4882a593Smuzhiyun 	SND_SOC_DAPM_OUTPUT("OUT"),
568*4882a593Smuzhiyun };
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun static const struct snd_soc_dapm_route tas2110_audio_map[] = {
571*4882a593Smuzhiyun 	{"ASI1 Sel", "I2C offset", "ASI1"},
572*4882a593Smuzhiyun 	{"ASI1 Sel", "Left", "ASI1"},
573*4882a593Smuzhiyun 	{"ASI1 Sel", "Right", "ASI1"},
574*4882a593Smuzhiyun 	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
575*4882a593Smuzhiyun 	{ "DAC", NULL, "ASI1 Sel" },
576*4882a593Smuzhiyun 	{ "OUT", NULL, "DAC" },
577*4882a593Smuzhiyun };
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_component_dev_tas2110 = {
580*4882a593Smuzhiyun 	.probe			= tas2562_codec_probe,
581*4882a593Smuzhiyun 	.suspend		= tas2562_suspend,
582*4882a593Smuzhiyun 	.resume			= tas2562_resume,
583*4882a593Smuzhiyun 	.set_bias_level		= tas2562_set_bias_level,
584*4882a593Smuzhiyun 	.controls		= tas2562_snd_controls,
585*4882a593Smuzhiyun 	.num_controls		= ARRAY_SIZE(tas2562_snd_controls),
586*4882a593Smuzhiyun 	.dapm_widgets		= tas2110_dapm_widgets,
587*4882a593Smuzhiyun 	.num_dapm_widgets	= ARRAY_SIZE(tas2110_dapm_widgets),
588*4882a593Smuzhiyun 	.dapm_routes		= tas2110_audio_map,
589*4882a593Smuzhiyun 	.num_dapm_routes	= ARRAY_SIZE(tas2110_audio_map),
590*4882a593Smuzhiyun 	.idle_bias_on		= 1,
591*4882a593Smuzhiyun 	.use_pmdown_time	= 1,
592*4882a593Smuzhiyun 	.endianness		= 1,
593*4882a593Smuzhiyun 	.non_legacy_dai_naming	= 1,
594*4882a593Smuzhiyun };
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
597*4882a593Smuzhiyun 	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
598*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
599*4882a593Smuzhiyun 	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
600*4882a593Smuzhiyun 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
601*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch),
602*4882a593Smuzhiyun 	SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch),
603*4882a593Smuzhiyun 	SND_SOC_DAPM_SIGGEN("VMON"),
604*4882a593Smuzhiyun 	SND_SOC_DAPM_SIGGEN("IMON"),
605*4882a593Smuzhiyun 	SND_SOC_DAPM_OUTPUT("OUT"),
606*4882a593Smuzhiyun };
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun static const struct snd_soc_dapm_route tas2562_audio_map[] = {
609*4882a593Smuzhiyun 	{"ASI1 Sel", "I2C offset", "ASI1"},
610*4882a593Smuzhiyun 	{"ASI1 Sel", "Left", "ASI1"},
611*4882a593Smuzhiyun 	{"ASI1 Sel", "Right", "ASI1"},
612*4882a593Smuzhiyun 	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
613*4882a593Smuzhiyun 	{ "DAC", NULL, "ASI1 Sel" },
614*4882a593Smuzhiyun 	{ "OUT", NULL, "DAC" },
615*4882a593Smuzhiyun 	{"ISENSE", "Switch", "IMON"},
616*4882a593Smuzhiyun 	{"VSENSE", "Switch", "VMON"},
617*4882a593Smuzhiyun };
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_component_dev_tas2562 = {
620*4882a593Smuzhiyun 	.probe			= tas2562_codec_probe,
621*4882a593Smuzhiyun 	.suspend		= tas2562_suspend,
622*4882a593Smuzhiyun 	.resume			= tas2562_resume,
623*4882a593Smuzhiyun 	.set_bias_level		= tas2562_set_bias_level,
624*4882a593Smuzhiyun 	.controls		= tas2562_snd_controls,
625*4882a593Smuzhiyun 	.num_controls		= ARRAY_SIZE(tas2562_snd_controls),
626*4882a593Smuzhiyun 	.dapm_widgets		= tas2562_dapm_widgets,
627*4882a593Smuzhiyun 	.num_dapm_widgets	= ARRAY_SIZE(tas2562_dapm_widgets),
628*4882a593Smuzhiyun 	.dapm_routes		= tas2562_audio_map,
629*4882a593Smuzhiyun 	.num_dapm_routes	= ARRAY_SIZE(tas2562_audio_map),
630*4882a593Smuzhiyun 	.idle_bias_on		= 1,
631*4882a593Smuzhiyun 	.use_pmdown_time	= 1,
632*4882a593Smuzhiyun 	.endianness		= 1,
633*4882a593Smuzhiyun 	.non_legacy_dai_naming	= 1,
634*4882a593Smuzhiyun };
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = {
637*4882a593Smuzhiyun 	.hw_params	= tas2562_hw_params,
638*4882a593Smuzhiyun 	.set_fmt	= tas2562_set_dai_fmt,
639*4882a593Smuzhiyun 	.set_tdm_slot	= tas2562_set_dai_tdm_slot,
640*4882a593Smuzhiyun 	.mute_stream	= tas2562_mute,
641*4882a593Smuzhiyun 	.no_capture_mute = 1,
642*4882a593Smuzhiyun };
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun static struct snd_soc_dai_driver tas2562_dai[] = {
645*4882a593Smuzhiyun 	{
646*4882a593Smuzhiyun 		.name = "tas2562-amplifier",
647*4882a593Smuzhiyun 		.id = 0,
648*4882a593Smuzhiyun 		.playback = {
649*4882a593Smuzhiyun 			.stream_name    = "ASI1 Playback",
650*4882a593Smuzhiyun 			.channels_min   = 2,
651*4882a593Smuzhiyun 			.channels_max   = 2,
652*4882a593Smuzhiyun 			.rates      = SNDRV_PCM_RATE_8000_192000,
653*4882a593Smuzhiyun 			.formats    = TAS2562_FORMATS,
654*4882a593Smuzhiyun 		},
655*4882a593Smuzhiyun 		.capture = {
656*4882a593Smuzhiyun 			.stream_name    = "ASI1 Capture",
657*4882a593Smuzhiyun 			.channels_min   = 0,
658*4882a593Smuzhiyun 			.channels_max   = 2,
659*4882a593Smuzhiyun 			.rates		= SNDRV_PCM_RATE_8000_192000,
660*4882a593Smuzhiyun 			.formats	= TAS2562_FORMATS,
661*4882a593Smuzhiyun 		},
662*4882a593Smuzhiyun 		.ops = &tas2562_speaker_dai_ops,
663*4882a593Smuzhiyun 	},
664*4882a593Smuzhiyun };
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun static const struct regmap_range_cfg tas2562_ranges[] = {
667*4882a593Smuzhiyun 	{
668*4882a593Smuzhiyun 		.range_min = 0,
669*4882a593Smuzhiyun 		.range_max = 5 * 128,
670*4882a593Smuzhiyun 		.selector_reg = TAS2562_PAGE_CTRL,
671*4882a593Smuzhiyun 		.selector_mask = 0xff,
672*4882a593Smuzhiyun 		.selector_shift = 0,
673*4882a593Smuzhiyun 		.window_start = 0,
674*4882a593Smuzhiyun 		.window_len = 128,
675*4882a593Smuzhiyun 	},
676*4882a593Smuzhiyun };
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun static const struct reg_default tas2562_reg_defaults[] = {
679*4882a593Smuzhiyun 	{ TAS2562_PAGE_CTRL, 0x00 },
680*4882a593Smuzhiyun 	{ TAS2562_SW_RESET, 0x00 },
681*4882a593Smuzhiyun 	{ TAS2562_PWR_CTRL, 0x0e },
682*4882a593Smuzhiyun 	{ TAS2562_PB_CFG1, 0x20 },
683*4882a593Smuzhiyun 	{ TAS2562_TDM_CFG0, 0x09 },
684*4882a593Smuzhiyun 	{ TAS2562_TDM_CFG1, 0x02 },
685*4882a593Smuzhiyun 	{ TAS2562_DVC_CFG1, 0x40 },
686*4882a593Smuzhiyun 	{ TAS2562_DVC_CFG2, 0x40 },
687*4882a593Smuzhiyun 	{ TAS2562_DVC_CFG3, 0x00 },
688*4882a593Smuzhiyun 	{ TAS2562_DVC_CFG4, 0x00 },
689*4882a593Smuzhiyun };
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun static const struct regmap_config tas2562_regmap_config = {
692*4882a593Smuzhiyun 	.reg_bits = 8,
693*4882a593Smuzhiyun 	.val_bits = 8,
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	.max_register = 5 * 128,
696*4882a593Smuzhiyun 	.cache_type = REGCACHE_RBTREE,
697*4882a593Smuzhiyun 	.reg_defaults = tas2562_reg_defaults,
698*4882a593Smuzhiyun 	.num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults),
699*4882a593Smuzhiyun 	.ranges = tas2562_ranges,
700*4882a593Smuzhiyun 	.num_ranges = ARRAY_SIZE(tas2562_ranges),
701*4882a593Smuzhiyun };
702*4882a593Smuzhiyun 
tas2562_parse_dt(struct tas2562_data * tas2562)703*4882a593Smuzhiyun static int tas2562_parse_dt(struct tas2562_data *tas2562)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun 	struct device *dev = tas2562->dev;
706*4882a593Smuzhiyun 	int ret = 0;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
709*4882a593Smuzhiyun 	if (IS_ERR(tas2562->sdz_gpio)) {
710*4882a593Smuzhiyun 		if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
711*4882a593Smuzhiyun 			return -EPROBE_DEFER;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 		tas2562->sdz_gpio = NULL;
714*4882a593Smuzhiyun 	}
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	/*
717*4882a593Smuzhiyun 	 * The shut-down property is deprecated but needs to be checked for
718*4882a593Smuzhiyun 	 * backwards compatibility.
719*4882a593Smuzhiyun 	 */
720*4882a593Smuzhiyun 	if (tas2562->sdz_gpio == NULL) {
721*4882a593Smuzhiyun 		tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down",
722*4882a593Smuzhiyun 							      GPIOD_OUT_HIGH);
723*4882a593Smuzhiyun 		if (IS_ERR(tas2562->sdz_gpio))
724*4882a593Smuzhiyun 			if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
725*4882a593Smuzhiyun 				return -EPROBE_DEFER;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 		tas2562->sdz_gpio = NULL;
728*4882a593Smuzhiyun 	}
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	if (tas2562->model_id == TAS2110)
731*4882a593Smuzhiyun 		return ret;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
734*4882a593Smuzhiyun 			&tas2562->i_sense_slot);
735*4882a593Smuzhiyun 	if (ret) {
736*4882a593Smuzhiyun 		dev_err(dev, "Property %s is missing setting default slot\n",
737*4882a593Smuzhiyun 			"ti,imon-slot-no");
738*4882a593Smuzhiyun 		tas2562->i_sense_slot = 0;
739*4882a593Smuzhiyun 	}
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
743*4882a593Smuzhiyun 			&tas2562->v_sense_slot);
744*4882a593Smuzhiyun 	if (ret) {
745*4882a593Smuzhiyun 		dev_info(dev, "Property %s is missing setting default slot\n",
746*4882a593Smuzhiyun 			"ti,vmon-slot-no");
747*4882a593Smuzhiyun 		tas2562->v_sense_slot = 2;
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	if (tas2562->v_sense_slot < tas2562->i_sense_slot) {
751*4882a593Smuzhiyun 		dev_err(dev, "Vsense slot must be greater than Isense slot\n");
752*4882a593Smuzhiyun 		return -EINVAL;
753*4882a593Smuzhiyun 	}
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	return ret;
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun 
tas2562_probe(struct i2c_client * client,const struct i2c_device_id * id)758*4882a593Smuzhiyun static int tas2562_probe(struct i2c_client *client,
759*4882a593Smuzhiyun 			 const struct i2c_device_id *id)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	struct device *dev = &client->dev;
762*4882a593Smuzhiyun 	struct tas2562_data *data;
763*4882a593Smuzhiyun 	int ret;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
766*4882a593Smuzhiyun 	if (!data)
767*4882a593Smuzhiyun 		return -ENOMEM;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	data->client = client;
770*4882a593Smuzhiyun 	data->dev = &client->dev;
771*4882a593Smuzhiyun 	data->model_id = id->driver_data;
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	tas2562_parse_dt(data);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config);
776*4882a593Smuzhiyun 	if (IS_ERR(data->regmap)) {
777*4882a593Smuzhiyun 		ret = PTR_ERR(data->regmap);
778*4882a593Smuzhiyun 		dev_err(dev, "failed to allocate register map: %d\n", ret);
779*4882a593Smuzhiyun 		return ret;
780*4882a593Smuzhiyun 	}
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	dev_set_drvdata(&client->dev, data);
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	if (data->model_id == TAS2110)
785*4882a593Smuzhiyun 		return devm_snd_soc_register_component(dev,
786*4882a593Smuzhiyun 						       &soc_component_dev_tas2110,
787*4882a593Smuzhiyun 						       tas2562_dai,
788*4882a593Smuzhiyun 						       ARRAY_SIZE(tas2562_dai));
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562,
791*4882a593Smuzhiyun 					       tas2562_dai,
792*4882a593Smuzhiyun 					       ARRAY_SIZE(tas2562_dai));
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun static const struct i2c_device_id tas2562_id[] = {
797*4882a593Smuzhiyun 	{ "tas2562", TAS2562 },
798*4882a593Smuzhiyun 	{ "tas2563", TAS2563 },
799*4882a593Smuzhiyun 	{ "tas2564", TAS2564 },
800*4882a593Smuzhiyun 	{ "tas2110", TAS2110 },
801*4882a593Smuzhiyun 	{ }
802*4882a593Smuzhiyun };
803*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, tas2562_id);
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun static const struct of_device_id tas2562_of_match[] = {
806*4882a593Smuzhiyun 	{ .compatible = "ti,tas2562", },
807*4882a593Smuzhiyun 	{ .compatible = "ti,tas2563", },
808*4882a593Smuzhiyun 	{ .compatible = "ti,tas2564", },
809*4882a593Smuzhiyun 	{ .compatible = "ti,tas2110", },
810*4882a593Smuzhiyun 	{ },
811*4882a593Smuzhiyun };
812*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tas2562_of_match);
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun static struct i2c_driver tas2562_i2c_driver = {
815*4882a593Smuzhiyun 	.driver = {
816*4882a593Smuzhiyun 		.name = "tas2562",
817*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(tas2562_of_match),
818*4882a593Smuzhiyun 	},
819*4882a593Smuzhiyun 	.probe = tas2562_probe,
820*4882a593Smuzhiyun 	.id_table = tas2562_id,
821*4882a593Smuzhiyun };
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun module_i2c_driver(tas2562_i2c_driver);
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
826*4882a593Smuzhiyun MODULE_DESCRIPTION("TAS2562 Audio amplifier driver");
827*4882a593Smuzhiyun MODULE_LICENSE("GPL");
828