xref: /openbmc/linux/sound/soc/codecs/idt821034.c (revision 05f5504b)
1*e5116699SHerve Codina // SPDX-License-Identifier: GPL-2.0
2*e5116699SHerve Codina //
3*e5116699SHerve Codina // IDT821034 ALSA SoC driver
4*e5116699SHerve Codina //
5*e5116699SHerve Codina // Copyright 2022 CS GROUP France
6*e5116699SHerve Codina //
7*e5116699SHerve Codina // Author: Herve Codina <herve.codina@bootlin.com>
8*e5116699SHerve Codina 
9*e5116699SHerve Codina #include <linux/bitrev.h>
10*e5116699SHerve Codina #include <linux/gpio/driver.h>
11*e5116699SHerve Codina #include <linux/module.h>
12*e5116699SHerve Codina #include <linux/slab.h>
13*e5116699SHerve Codina #include <linux/spi/spi.h>
14*e5116699SHerve Codina #include <sound/pcm_params.h>
15*e5116699SHerve Codina #include <sound/soc.h>
16*e5116699SHerve Codina #include <sound/tlv.h>
17*e5116699SHerve Codina 
18*e5116699SHerve Codina #define IDT821034_NB_CHANNEL	4
19*e5116699SHerve Codina 
20*e5116699SHerve Codina struct idt821034_amp {
21*e5116699SHerve Codina 	u16 gain;
22*e5116699SHerve Codina 	bool is_muted;
23*e5116699SHerve Codina };
24*e5116699SHerve Codina 
25*e5116699SHerve Codina struct idt821034 {
26*e5116699SHerve Codina 	struct spi_device *spi;
27*e5116699SHerve Codina 	struct mutex mutex;
28*e5116699SHerve Codina 	u8 spi_tx_buf; /* Cannot use stack area for SPI (dma-safe memory) */
29*e5116699SHerve Codina 	u8 spi_rx_buf; /* Cannot use stack area for SPI (dma-safe memory) */
30*e5116699SHerve Codina 	struct {
31*e5116699SHerve Codina 		u8 codec_conf;
32*e5116699SHerve Codina 		struct {
33*e5116699SHerve Codina 			u8 power;
34*e5116699SHerve Codina 			u8 tx_slot;
35*e5116699SHerve Codina 			u8 rx_slot;
36*e5116699SHerve Codina 			u8 slic_conf;
37*e5116699SHerve Codina 			u8 slic_control;
38*e5116699SHerve Codina 		} ch[IDT821034_NB_CHANNEL];
39*e5116699SHerve Codina 	} cache;
40*e5116699SHerve Codina 	struct {
41*e5116699SHerve Codina 		struct {
42*e5116699SHerve Codina 			struct idt821034_amp amp_out;
43*e5116699SHerve Codina 			struct idt821034_amp amp_in;
44*e5116699SHerve Codina 		} ch[IDT821034_NB_CHANNEL];
45*e5116699SHerve Codina 	} amps;
46*e5116699SHerve Codina 	int max_ch_playback;
47*e5116699SHerve Codina 	int max_ch_capture;
48*e5116699SHerve Codina 	struct gpio_chip gpio_chip;
49*e5116699SHerve Codina };
50*e5116699SHerve Codina 
idt821034_8bit_write(struct idt821034 * idt821034,u8 val)51*e5116699SHerve Codina static int idt821034_8bit_write(struct idt821034 *idt821034, u8 val)
52*e5116699SHerve Codina {
53*e5116699SHerve Codina 	struct spi_transfer xfer[] = {
54*e5116699SHerve Codina 		{
55*e5116699SHerve Codina 			.tx_buf = &idt821034->spi_tx_buf,
56*e5116699SHerve Codina 			.len = 1,
57*e5116699SHerve Codina 		}, {
58*e5116699SHerve Codina 			.cs_off = 1,
59*e5116699SHerve Codina 			.tx_buf = &idt821034->spi_tx_buf,
60*e5116699SHerve Codina 			.len = 1,
61*e5116699SHerve Codina 		}
62*e5116699SHerve Codina 	};
63*e5116699SHerve Codina 
64*e5116699SHerve Codina 	idt821034->spi_tx_buf = val;
65*e5116699SHerve Codina 
66*e5116699SHerve Codina 	dev_vdbg(&idt821034->spi->dev, "spi xfer wr 0x%x\n", val);
67*e5116699SHerve Codina 
68*e5116699SHerve Codina 	return spi_sync_transfer(idt821034->spi, xfer, 2);
69*e5116699SHerve Codina }
70*e5116699SHerve Codina 
idt821034_2x8bit_write(struct idt821034 * idt821034,u8 val1,u8 val2)71*e5116699SHerve Codina static int idt821034_2x8bit_write(struct idt821034 *idt821034, u8 val1, u8 val2)
72*e5116699SHerve Codina {
73*e5116699SHerve Codina 	int ret;
74*e5116699SHerve Codina 
75*e5116699SHerve Codina 	ret = idt821034_8bit_write(idt821034, val1);
76*e5116699SHerve Codina 	if (ret)
77*e5116699SHerve Codina 		return ret;
78*e5116699SHerve Codina 	return idt821034_8bit_write(idt821034, val2);
79*e5116699SHerve Codina }
80*e5116699SHerve Codina 
idt821034_8bit_read(struct idt821034 * idt821034,u8 valw,u8 * valr)81*e5116699SHerve Codina static int idt821034_8bit_read(struct idt821034 *idt821034, u8 valw, u8 *valr)
82*e5116699SHerve Codina {
83*e5116699SHerve Codina 	struct spi_transfer xfer[] = {
84*e5116699SHerve Codina 		{
85*e5116699SHerve Codina 			.tx_buf = &idt821034->spi_tx_buf,
86*e5116699SHerve Codina 			.rx_buf = &idt821034->spi_rx_buf,
87*e5116699SHerve Codina 			.len = 1,
88*e5116699SHerve Codina 		}, {
89*e5116699SHerve Codina 			.cs_off = 1,
90*e5116699SHerve Codina 			.tx_buf = &idt821034->spi_tx_buf,
91*e5116699SHerve Codina 			.len = 1,
92*e5116699SHerve Codina 		}
93*e5116699SHerve Codina 	};
94*e5116699SHerve Codina 	int ret;
95*e5116699SHerve Codina 
96*e5116699SHerve Codina 	idt821034->spi_tx_buf = valw;
97*e5116699SHerve Codina 
98*e5116699SHerve Codina 	ret = spi_sync_transfer(idt821034->spi, xfer, 2);
99*e5116699SHerve Codina 	if (ret)
100*e5116699SHerve Codina 		return ret;
101*e5116699SHerve Codina 
102*e5116699SHerve Codina 	*valr = idt821034->spi_rx_buf;
103*e5116699SHerve Codina 
104*e5116699SHerve Codina 	dev_vdbg(&idt821034->spi->dev, "spi xfer wr 0x%x, rd 0x%x\n",
105*e5116699SHerve Codina 		 valw, *valr);
106*e5116699SHerve Codina 
107*e5116699SHerve Codina 	return 0;
108*e5116699SHerve Codina }
109*e5116699SHerve Codina 
110*e5116699SHerve Codina /* Available mode for the programming sequence */
111*e5116699SHerve Codina #define IDT821034_MODE_CODEC(_ch) (0x80 | ((_ch) << 2))
112*e5116699SHerve Codina #define IDT821034_MODE_SLIC(_ch)  (0xD0 | ((_ch) << 2))
113*e5116699SHerve Codina #define IDT821034_MODE_GAIN(_ch)  (0xC0 | ((_ch) << 2))
114*e5116699SHerve Codina 
115*e5116699SHerve Codina /* Power values that can be used in 'power' (can be ORed) */
116*e5116699SHerve Codina #define IDT821034_CONF_PWRUP_TX		BIT(1) /* from analog input to PCM */
117*e5116699SHerve Codina #define IDT821034_CONF_PWRUP_RX		BIT(0) /* from PCM to analog output */
118*e5116699SHerve Codina 
idt821034_set_channel_power(struct idt821034 * idt821034,u8 ch,u8 power)119*e5116699SHerve Codina static int idt821034_set_channel_power(struct idt821034 *idt821034, u8 ch, u8 power)
120*e5116699SHerve Codina {
121*e5116699SHerve Codina 	u8 conf;
122*e5116699SHerve Codina 	int ret;
123*e5116699SHerve Codina 
124*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "set_channel_power(%u, 0x%x)\n", ch, power);
125*e5116699SHerve Codina 
126*e5116699SHerve Codina 	conf = IDT821034_MODE_CODEC(ch) | idt821034->cache.codec_conf;
127*e5116699SHerve Codina 
128*e5116699SHerve Codina 	if (power & IDT821034_CONF_PWRUP_RX) {
129*e5116699SHerve Codina 		ret = idt821034_2x8bit_write(idt821034,
130*e5116699SHerve Codina 					     conf | IDT821034_CONF_PWRUP_RX,
131*e5116699SHerve Codina 					     idt821034->cache.ch[ch].rx_slot);
132*e5116699SHerve Codina 		if (ret)
133*e5116699SHerve Codina 			return ret;
134*e5116699SHerve Codina 	}
135*e5116699SHerve Codina 	if (power & IDT821034_CONF_PWRUP_TX) {
136*e5116699SHerve Codina 		ret = idt821034_2x8bit_write(idt821034,
137*e5116699SHerve Codina 					     conf | IDT821034_CONF_PWRUP_TX,
138*e5116699SHerve Codina 					     idt821034->cache.ch[ch].tx_slot);
139*e5116699SHerve Codina 		if (ret)
140*e5116699SHerve Codina 			return ret;
141*e5116699SHerve Codina 	}
142*e5116699SHerve Codina 	if (!(power & (IDT821034_CONF_PWRUP_TX | IDT821034_CONF_PWRUP_RX))) {
143*e5116699SHerve Codina 		ret = idt821034_2x8bit_write(idt821034, conf, 0);
144*e5116699SHerve Codina 		if (ret)
145*e5116699SHerve Codina 			return ret;
146*e5116699SHerve Codina 	}
147*e5116699SHerve Codina 
148*e5116699SHerve Codina 	idt821034->cache.ch[ch].power = power;
149*e5116699SHerve Codina 
150*e5116699SHerve Codina 	return 0;
151*e5116699SHerve Codina }
152*e5116699SHerve Codina 
idt821034_get_channel_power(struct idt821034 * idt821034,u8 ch)153*e5116699SHerve Codina static u8 idt821034_get_channel_power(struct idt821034 *idt821034, u8 ch)
154*e5116699SHerve Codina {
155*e5116699SHerve Codina 	return idt821034->cache.ch[ch].power;
156*e5116699SHerve Codina }
157*e5116699SHerve Codina 
158*e5116699SHerve Codina /* Codec configuration values that can be used in 'codec_conf' (can be ORed) */
159*e5116699SHerve Codina #define IDT821034_CONF_ALAW_MODE	BIT(5)
160*e5116699SHerve Codina #define IDT821034_CONF_DELAY_MODE	BIT(4)
161*e5116699SHerve Codina 
idt821034_set_codec_conf(struct idt821034 * idt821034,u8 codec_conf)162*e5116699SHerve Codina static int idt821034_set_codec_conf(struct idt821034 *idt821034, u8 codec_conf)
163*e5116699SHerve Codina {
164*e5116699SHerve Codina 	u8 conf;
165*e5116699SHerve Codina 	u8 ts;
166*e5116699SHerve Codina 	int ret;
167*e5116699SHerve Codina 
168*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "set_codec_conf(0x%x)\n", codec_conf);
169*e5116699SHerve Codina 
170*e5116699SHerve Codina 	/* codec conf fields are common to all channel.
171*e5116699SHerve Codina 	 * Arbitrary use of channel 0 for this configuration.
172*e5116699SHerve Codina 	 */
173*e5116699SHerve Codina 
174*e5116699SHerve Codina 	/* Set Configuration Register */
175*e5116699SHerve Codina 	conf = IDT821034_MODE_CODEC(0) | codec_conf;
176*e5116699SHerve Codina 
177*e5116699SHerve Codina 	/* Update conf value and timeslot register value according
178*e5116699SHerve Codina 	 * to cache values
179*e5116699SHerve Codina 	 */
180*e5116699SHerve Codina 	if (idt821034->cache.ch[0].power & IDT821034_CONF_PWRUP_RX) {
181*e5116699SHerve Codina 		conf |= IDT821034_CONF_PWRUP_RX;
182*e5116699SHerve Codina 		ts = idt821034->cache.ch[0].rx_slot;
183*e5116699SHerve Codina 	} else if (idt821034->cache.ch[0].power & IDT821034_CONF_PWRUP_TX) {
184*e5116699SHerve Codina 		conf |= IDT821034_CONF_PWRUP_TX;
185*e5116699SHerve Codina 		ts = idt821034->cache.ch[0].tx_slot;
186*e5116699SHerve Codina 	} else {
187*e5116699SHerve Codina 		ts = 0x00;
188*e5116699SHerve Codina 	}
189*e5116699SHerve Codina 
190*e5116699SHerve Codina 	/* Write configuration register and time-slot register */
191*e5116699SHerve Codina 	ret = idt821034_2x8bit_write(idt821034, conf, ts);
192*e5116699SHerve Codina 	if (ret)
193*e5116699SHerve Codina 		return ret;
194*e5116699SHerve Codina 
195*e5116699SHerve Codina 	idt821034->cache.codec_conf = codec_conf;
196*e5116699SHerve Codina 	return 0;
197*e5116699SHerve Codina }
198*e5116699SHerve Codina 
idt821034_get_codec_conf(struct idt821034 * idt821034)199*e5116699SHerve Codina static u8 idt821034_get_codec_conf(struct idt821034 *idt821034)
200*e5116699SHerve Codina {
201*e5116699SHerve Codina 	return idt821034->cache.codec_conf;
202*e5116699SHerve Codina }
203*e5116699SHerve Codina 
204*e5116699SHerve Codina /* Channel direction values that can be used in 'ch_dir' (can be ORed) */
205*e5116699SHerve Codina #define IDT821034_CH_RX		BIT(0) /* from PCM to analog output */
206*e5116699SHerve Codina #define IDT821034_CH_TX		BIT(1) /* from analog input to PCM */
207*e5116699SHerve Codina 
idt821034_set_channel_ts(struct idt821034 * idt821034,u8 ch,u8 ch_dir,u8 ts_num)208*e5116699SHerve Codina static int idt821034_set_channel_ts(struct idt821034 *idt821034, u8 ch, u8 ch_dir, u8 ts_num)
209*e5116699SHerve Codina {
210*e5116699SHerve Codina 	u8 conf;
211*e5116699SHerve Codina 	int ret;
212*e5116699SHerve Codina 
213*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "set_channel_ts(%u, 0x%x, %d)\n", ch, ch_dir, ts_num);
214*e5116699SHerve Codina 
215*e5116699SHerve Codina 	conf = IDT821034_MODE_CODEC(ch) | idt821034->cache.codec_conf;
216*e5116699SHerve Codina 
217*e5116699SHerve Codina 	if (ch_dir & IDT821034_CH_RX) {
218*e5116699SHerve Codina 		if (idt821034->cache.ch[ch].power & IDT821034_CONF_PWRUP_RX) {
219*e5116699SHerve Codina 			ret = idt821034_2x8bit_write(idt821034,
220*e5116699SHerve Codina 						     conf | IDT821034_CONF_PWRUP_RX,
221*e5116699SHerve Codina 						     ts_num);
222*e5116699SHerve Codina 			if (ret)
223*e5116699SHerve Codina 				return ret;
224*e5116699SHerve Codina 		}
225*e5116699SHerve Codina 		idt821034->cache.ch[ch].rx_slot = ts_num;
226*e5116699SHerve Codina 	}
227*e5116699SHerve Codina 	if (ch_dir & IDT821034_CH_TX) {
228*e5116699SHerve Codina 		if (idt821034->cache.ch[ch].power & IDT821034_CONF_PWRUP_TX) {
229*e5116699SHerve Codina 			ret = idt821034_2x8bit_write(idt821034,
230*e5116699SHerve Codina 						     conf | IDT821034_CONF_PWRUP_TX,
231*e5116699SHerve Codina 						     ts_num);
232*e5116699SHerve Codina 			if (ret)
233*e5116699SHerve Codina 				return ret;
234*e5116699SHerve Codina 		}
235*e5116699SHerve Codina 		idt821034->cache.ch[ch].tx_slot = ts_num;
236*e5116699SHerve Codina 	}
237*e5116699SHerve Codina 
238*e5116699SHerve Codina 	return 0;
239*e5116699SHerve Codina }
240*e5116699SHerve Codina 
241*e5116699SHerve Codina /* SLIC direction values that can be used in 'slic_dir' (can be ORed) */
242*e5116699SHerve Codina #define IDT821034_SLIC_IO1_IN       BIT(1)
243*e5116699SHerve Codina #define IDT821034_SLIC_IO0_IN       BIT(0)
244*e5116699SHerve Codina 
idt821034_set_slic_conf(struct idt821034 * idt821034,u8 ch,u8 slic_dir)245*e5116699SHerve Codina static int idt821034_set_slic_conf(struct idt821034 *idt821034, u8 ch, u8 slic_dir)
246*e5116699SHerve Codina {
247*e5116699SHerve Codina 	u8 conf;
248*e5116699SHerve Codina 	int ret;
249*e5116699SHerve Codina 
250*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "set_slic_conf(%u, 0x%x)\n", ch, slic_dir);
251*e5116699SHerve Codina 
252*e5116699SHerve Codina 	conf = IDT821034_MODE_SLIC(ch) | slic_dir;
253*e5116699SHerve Codina 	ret = idt821034_2x8bit_write(idt821034, conf, idt821034->cache.ch[ch].slic_control);
254*e5116699SHerve Codina 	if (ret)
255*e5116699SHerve Codina 		return ret;
256*e5116699SHerve Codina 
257*e5116699SHerve Codina 	idt821034->cache.ch[ch].slic_conf = slic_dir;
258*e5116699SHerve Codina 
259*e5116699SHerve Codina 	return 0;
260*e5116699SHerve Codina }
261*e5116699SHerve Codina 
idt821034_get_slic_conf(struct idt821034 * idt821034,u8 ch)262*e5116699SHerve Codina static u8 idt821034_get_slic_conf(struct idt821034 *idt821034, u8 ch)
263*e5116699SHerve Codina {
264*e5116699SHerve Codina 	return idt821034->cache.ch[ch].slic_conf;
265*e5116699SHerve Codina }
266*e5116699SHerve Codina 
idt821034_write_slic_raw(struct idt821034 * idt821034,u8 ch,u8 slic_raw)267*e5116699SHerve Codina static int idt821034_write_slic_raw(struct idt821034 *idt821034, u8 ch, u8 slic_raw)
268*e5116699SHerve Codina {
269*e5116699SHerve Codina 	u8 conf;
270*e5116699SHerve Codina 	int ret;
271*e5116699SHerve Codina 
272*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "write_slic_raw(%u, 0x%x)\n", ch, slic_raw);
273*e5116699SHerve Codina 
274*e5116699SHerve Codina 	/*
275*e5116699SHerve Codina 	 * On write, slic_raw is mapped as follow :
276*e5116699SHerve Codina 	 *   b4: O_4
277*e5116699SHerve Codina 	 *   b3: O_3
278*e5116699SHerve Codina 	 *   b2: O_2
279*e5116699SHerve Codina 	 *   b1: I/O_1
280*e5116699SHerve Codina 	 *   b0: I/O_0
281*e5116699SHerve Codina 	 */
282*e5116699SHerve Codina 
283*e5116699SHerve Codina 	conf = IDT821034_MODE_SLIC(ch) | idt821034->cache.ch[ch].slic_conf;
284*e5116699SHerve Codina 	ret = idt821034_2x8bit_write(idt821034, conf, slic_raw);
285*e5116699SHerve Codina 	if (ret)
286*e5116699SHerve Codina 		return ret;
287*e5116699SHerve Codina 
288*e5116699SHerve Codina 	idt821034->cache.ch[ch].slic_control = slic_raw;
289*e5116699SHerve Codina 	return 0;
290*e5116699SHerve Codina }
291*e5116699SHerve Codina 
idt821034_get_written_slic_raw(struct idt821034 * idt821034,u8 ch)292*e5116699SHerve Codina static u8 idt821034_get_written_slic_raw(struct idt821034 *idt821034, u8 ch)
293*e5116699SHerve Codina {
294*e5116699SHerve Codina 	return idt821034->cache.ch[ch].slic_control;
295*e5116699SHerve Codina }
296*e5116699SHerve Codina 
idt821034_read_slic_raw(struct idt821034 * idt821034,u8 ch,u8 * slic_raw)297*e5116699SHerve Codina static int idt821034_read_slic_raw(struct idt821034 *idt821034, u8 ch, u8 *slic_raw)
298*e5116699SHerve Codina {
299*e5116699SHerve Codina 	u8 val;
300*e5116699SHerve Codina 	int ret;
301*e5116699SHerve Codina 
302*e5116699SHerve Codina 	/*
303*e5116699SHerve Codina 	 * On read, slic_raw is mapped as follow :
304*e5116699SHerve Codina 	 *   b7: I/O_0
305*e5116699SHerve Codina 	 *   b6: I/O_1
306*e5116699SHerve Codina 	 *   b5: O_2
307*e5116699SHerve Codina 	 *   b4: O_3
308*e5116699SHerve Codina 	 *   b3: O_4
309*e5116699SHerve Codina 	 *   b2: I/O1_0, I/O_0 from channel 1 (no matter ch value)
310*e5116699SHerve Codina 	 *   b1: I/O2_0, I/O_0 from channel 2 (no matter ch value)
311*e5116699SHerve Codina 	 *   b2: I/O3_0, I/O_0 from channel 3 (no matter ch value)
312*e5116699SHerve Codina 	 */
313*e5116699SHerve Codina 
314*e5116699SHerve Codina 	val = IDT821034_MODE_SLIC(ch) | idt821034->cache.ch[ch].slic_conf;
315*e5116699SHerve Codina 	ret = idt821034_8bit_write(idt821034, val);
316*e5116699SHerve Codina 	if (ret)
317*e5116699SHerve Codina 		return ret;
318*e5116699SHerve Codina 
319*e5116699SHerve Codina 	ret = idt821034_8bit_read(idt821034, idt821034->cache.ch[ch].slic_control, slic_raw);
320*e5116699SHerve Codina 	if (ret)
321*e5116699SHerve Codina 		return ret;
322*e5116699SHerve Codina 
323*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "read_slic_raw(%i) 0x%x\n", ch, *slic_raw);
324*e5116699SHerve Codina 
325*e5116699SHerve Codina 	return 0;
326*e5116699SHerve Codina }
327*e5116699SHerve Codina 
328*e5116699SHerve Codina /* Gain type values that can be used in 'gain_type' (cannot be ORed) */
329*e5116699SHerve Codina #define IDT821034_GAIN_RX		(0 << 1) /* from PCM to analog output */
330*e5116699SHerve Codina #define IDT821034_GAIN_TX		(1 << 1) /* from analog input to PCM */
331*e5116699SHerve Codina 
idt821034_set_gain_channel(struct idt821034 * idt821034,u8 ch,u8 gain_type,u16 gain_val)332*e5116699SHerve Codina static int idt821034_set_gain_channel(struct idt821034 *idt821034, u8 ch,
333*e5116699SHerve Codina 				      u8 gain_type, u16 gain_val)
334*e5116699SHerve Codina {
335*e5116699SHerve Codina 	u8 conf;
336*e5116699SHerve Codina 	int ret;
337*e5116699SHerve Codina 
338*e5116699SHerve Codina 	dev_dbg(&idt821034->spi->dev, "set_gain_channel(%u, 0x%x, 0x%x-%d)\n",
339*e5116699SHerve Codina 		ch, gain_type, gain_val, gain_val);
340*e5116699SHerve Codina 
341*e5116699SHerve Codina 	/*
342*e5116699SHerve Codina 	 * The gain programming coefficients should be calculated as:
343*e5116699SHerve Codina 	 *   Transmit : Coeff_X = round [ gain_X0dB × gain_X ]
344*e5116699SHerve Codina 	 *   Receive: Coeff_R = round [ gain_R0dB × gain_R ]
345*e5116699SHerve Codina 	 * where:
346*e5116699SHerve Codina 	 *   gain_X0dB = 1820;
347*e5116699SHerve Codina 	 *   gain_X is the target gain;
348*e5116699SHerve Codina 	 *   Coeff_X should be in the range of 0 to 8192.
349*e5116699SHerve Codina 	 *   gain_R0dB = 2506;
350*e5116699SHerve Codina 	 *   gain_R is the target gain;
351*e5116699SHerve Codina 	 *   Coeff_R should be in the range of 0 to 8192.
352*e5116699SHerve Codina 	 *
353*e5116699SHerve Codina 	 * A gain programming coefficient is 14-bit wide and in binary format.
354*e5116699SHerve Codina 	 * The 7 Most Significant Bits of the coefficient is called
355*e5116699SHerve Codina 	 * GA_MSB_Transmit for transmit path, or is called GA_MSB_Receive for
356*e5116699SHerve Codina 	 * receive path; The 7 Least Significant Bits of the coefficient is
357*e5116699SHerve Codina 	 * called GA_LSB_ Transmit for transmit path, or is called
358*e5116699SHerve Codina 	 * GA_LSB_Receive for receive path.
359*e5116699SHerve Codina 	 *
360*e5116699SHerve Codina 	 * An example is given below to clarify the calculation of the
361*e5116699SHerve Codina 	 * coefficient. To program a +3 dB gain in transmit path and a -3.5 dB
362*e5116699SHerve Codina 	 * gain in receive path:
363*e5116699SHerve Codina 	 *
364*e5116699SHerve Codina 	 * Linear Code of +3dB = 10^(3/20)= 1.412537545
365*e5116699SHerve Codina 	 * Coeff_X = round (1820 × 1.412537545) = 2571
366*e5116699SHerve Codina 	 *                                      = 0b001010_00001011
367*e5116699SHerve Codina 	 * GA_MSB_Transmit = 0b0010100
368*e5116699SHerve Codina 	 * GA_LSB_Transmit = 0b0001011
369*e5116699SHerve Codina 	 *
370*e5116699SHerve Codina 	 * Linear Code of -3.5dB = 10^(-3.5/20) = 0.668343917
371*e5116699SHerve Codina 	 * Coeff_R= round (2506 × 0.668343917) = 1675
372*e5116699SHerve Codina 	 *                                     = 0b0001101_0001011
373*e5116699SHerve Codina 	 * GA_MSB_Receive = 0b0001101
374*e5116699SHerve Codina 	 * GA_LSB_Receive = 0b0001011
375*e5116699SHerve Codina 	 */
376*e5116699SHerve Codina 
377*e5116699SHerve Codina 	conf = IDT821034_MODE_GAIN(ch) | gain_type;
378*e5116699SHerve Codina 
379*e5116699SHerve Codina 	ret = idt821034_2x8bit_write(idt821034, conf | 0x00, gain_val & 0x007F);
380*e5116699SHerve Codina 	if (ret)
381*e5116699SHerve Codina 		return ret;
382*e5116699SHerve Codina 
383*e5116699SHerve Codina 	ret = idt821034_2x8bit_write(idt821034, conf | 0x01, (gain_val >> 7) & 0x7F);
384*e5116699SHerve Codina 	if (ret)
385*e5116699SHerve Codina 		return ret;
386*e5116699SHerve Codina 
387*e5116699SHerve Codina 	return 0;
388*e5116699SHerve Codina }
389*e5116699SHerve Codina 
390*e5116699SHerve Codina /* Id helpers used in controls and dapm */
391*e5116699SHerve Codina #define IDT821034_DIR_OUT (1 << 3)
392*e5116699SHerve Codina #define IDT821034_DIR_IN  (0 << 3)
393*e5116699SHerve Codina #define IDT821034_ID(_ch, _dir) (((_ch) & 0x03) | (_dir))
394*e5116699SHerve Codina #define IDT821034_ID_OUT(_ch) IDT821034_ID(_ch, IDT821034_DIR_OUT)
395*e5116699SHerve Codina #define IDT821034_ID_IN(_ch)  IDT821034_ID(_ch, IDT821034_DIR_IN)
396*e5116699SHerve Codina 
397*e5116699SHerve Codina #define IDT821034_ID_GET_CHAN(_id) ((_id) & 0x03)
398*e5116699SHerve Codina #define IDT821034_ID_GET_DIR(_id) ((_id) & (1 << 3))
399*e5116699SHerve Codina #define IDT821034_ID_IS_OUT(_id) (IDT821034_ID_GET_DIR(_id) == IDT821034_DIR_OUT)
400*e5116699SHerve Codina 
idt821034_kctrl_gain_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)401*e5116699SHerve Codina static int idt821034_kctrl_gain_get(struct snd_kcontrol *kcontrol,
402*e5116699SHerve Codina 				    struct snd_ctl_elem_value *ucontrol)
403*e5116699SHerve Codina {
404*e5116699SHerve Codina 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
405*e5116699SHerve Codina 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
406*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
407*e5116699SHerve Codina 	int min = mc->min;
408*e5116699SHerve Codina 	int max = mc->max;
409*e5116699SHerve Codina 	unsigned int mask = (1 << fls(max)) - 1;
410*e5116699SHerve Codina 	unsigned int invert = mc->invert;
411*e5116699SHerve Codina 	int val;
412*e5116699SHerve Codina 	u8 ch;
413*e5116699SHerve Codina 
414*e5116699SHerve Codina 	ch = IDT821034_ID_GET_CHAN(mc->reg);
415*e5116699SHerve Codina 
416*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
417*e5116699SHerve Codina 	if (IDT821034_ID_IS_OUT(mc->reg))
418*e5116699SHerve Codina 		val = idt821034->amps.ch[ch].amp_out.gain;
419*e5116699SHerve Codina 	else
420*e5116699SHerve Codina 		val = idt821034->amps.ch[ch].amp_in.gain;
421*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
422*e5116699SHerve Codina 
423*e5116699SHerve Codina 	ucontrol->value.integer.value[0] = val & mask;
424*e5116699SHerve Codina 	if (invert)
425*e5116699SHerve Codina 		ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0];
426*e5116699SHerve Codina 	else
427*e5116699SHerve Codina 		ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] - min;
428*e5116699SHerve Codina 
429*e5116699SHerve Codina 	return 0;
430*e5116699SHerve Codina }
431*e5116699SHerve Codina 
idt821034_kctrl_gain_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)432*e5116699SHerve Codina static int idt821034_kctrl_gain_put(struct snd_kcontrol *kcontrol,
433*e5116699SHerve Codina 				    struct snd_ctl_elem_value *ucontrol)
434*e5116699SHerve Codina {
435*e5116699SHerve Codina 	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
436*e5116699SHerve Codina 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
437*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
438*e5116699SHerve Codina 	struct idt821034_amp *amp;
439*e5116699SHerve Codina 	int min = mc->min;
440*e5116699SHerve Codina 	int max = mc->max;
441*e5116699SHerve Codina 	unsigned int mask = (1 << fls(max)) - 1;
442*e5116699SHerve Codina 	unsigned int invert = mc->invert;
443*e5116699SHerve Codina 	unsigned int val;
444*e5116699SHerve Codina 	int ret;
445*e5116699SHerve Codina 	u8 gain_type;
446*e5116699SHerve Codina 	u8 ch;
447*e5116699SHerve Codina 
448*e5116699SHerve Codina 	val = ucontrol->value.integer.value[0];
449*e5116699SHerve Codina 	if (val > max - min)
450*e5116699SHerve Codina 		return -EINVAL;
451*e5116699SHerve Codina 
452*e5116699SHerve Codina 	if (invert)
453*e5116699SHerve Codina 		val = (max - val) & mask;
454*e5116699SHerve Codina 	else
455*e5116699SHerve Codina 		val = (val + min) & mask;
456*e5116699SHerve Codina 
457*e5116699SHerve Codina 	ch = IDT821034_ID_GET_CHAN(mc->reg);
458*e5116699SHerve Codina 
459*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
460*e5116699SHerve Codina 
461*e5116699SHerve Codina 	if (IDT821034_ID_IS_OUT(mc->reg)) {
462*e5116699SHerve Codina 		amp = &idt821034->amps.ch[ch].amp_out;
463*e5116699SHerve Codina 		gain_type = IDT821034_GAIN_RX;
464*e5116699SHerve Codina 	} else {
465*e5116699SHerve Codina 		amp = &idt821034->amps.ch[ch].amp_in;
466*e5116699SHerve Codina 		gain_type = IDT821034_GAIN_TX;
467*e5116699SHerve Codina 	}
468*e5116699SHerve Codina 
469*e5116699SHerve Codina 	if (amp->gain == val) {
470*e5116699SHerve Codina 		ret = 0;
471*e5116699SHerve Codina 		goto end;
472*e5116699SHerve Codina 	}
473*e5116699SHerve Codina 
474*e5116699SHerve Codina 	if (!amp->is_muted) {
475*e5116699SHerve Codina 		ret = idt821034_set_gain_channel(idt821034, ch, gain_type, val);
476*e5116699SHerve Codina 		if (ret)
477*e5116699SHerve Codina 			goto end;
478*e5116699SHerve Codina 	}
479*e5116699SHerve Codina 
480*e5116699SHerve Codina 	amp->gain = val;
481*e5116699SHerve Codina 	ret = 1; /* The value changed */
482*e5116699SHerve Codina end:
483*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
484*e5116699SHerve Codina 	return ret;
485*e5116699SHerve Codina }
486*e5116699SHerve Codina 
idt821034_kctrl_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)487*e5116699SHerve Codina static int idt821034_kctrl_mute_get(struct snd_kcontrol *kcontrol,
488*e5116699SHerve Codina 				    struct snd_ctl_elem_value *ucontrol)
489*e5116699SHerve Codina {
490*e5116699SHerve Codina 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
491*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
492*e5116699SHerve Codina 	int id = kcontrol->private_value;
493*e5116699SHerve Codina 	bool is_muted;
494*e5116699SHerve Codina 	u8 ch;
495*e5116699SHerve Codina 
496*e5116699SHerve Codina 	ch = IDT821034_ID_GET_CHAN(id);
497*e5116699SHerve Codina 
498*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
499*e5116699SHerve Codina 	is_muted = IDT821034_ID_IS_OUT(id) ?
500*e5116699SHerve Codina 			idt821034->amps.ch[ch].amp_out.is_muted :
501*e5116699SHerve Codina 			idt821034->amps.ch[ch].amp_in.is_muted;
502*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
503*e5116699SHerve Codina 
504*e5116699SHerve Codina 	ucontrol->value.integer.value[0] = !is_muted;
505*e5116699SHerve Codina 
506*e5116699SHerve Codina 	return 0;
507*e5116699SHerve Codina }
508*e5116699SHerve Codina 
idt821034_kctrl_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)509*e5116699SHerve Codina static int idt821034_kctrl_mute_put(struct snd_kcontrol *kcontrol,
510*e5116699SHerve Codina 				    struct snd_ctl_elem_value *ucontrol)
511*e5116699SHerve Codina {
512*e5116699SHerve Codina 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
513*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
514*e5116699SHerve Codina 	int id = kcontrol->private_value;
515*e5116699SHerve Codina 	struct idt821034_amp *amp;
516*e5116699SHerve Codina 	bool is_mute;
517*e5116699SHerve Codina 	u8 gain_type;
518*e5116699SHerve Codina 	int ret;
519*e5116699SHerve Codina 	u8 ch;
520*e5116699SHerve Codina 
521*e5116699SHerve Codina 	ch = IDT821034_ID_GET_CHAN(id);
522*e5116699SHerve Codina 	is_mute = !ucontrol->value.integer.value[0];
523*e5116699SHerve Codina 
524*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
525*e5116699SHerve Codina 
526*e5116699SHerve Codina 	if (IDT821034_ID_IS_OUT(id)) {
527*e5116699SHerve Codina 		amp = &idt821034->amps.ch[ch].amp_out;
528*e5116699SHerve Codina 		gain_type = IDT821034_GAIN_RX;
529*e5116699SHerve Codina 	} else {
530*e5116699SHerve Codina 		amp = &idt821034->amps.ch[ch].amp_in;
531*e5116699SHerve Codina 		gain_type = IDT821034_GAIN_TX;
532*e5116699SHerve Codina 	}
533*e5116699SHerve Codina 
534*e5116699SHerve Codina 	if (amp->is_muted == is_mute) {
535*e5116699SHerve Codina 		ret = 0;
536*e5116699SHerve Codina 		goto end;
537*e5116699SHerve Codina 	}
538*e5116699SHerve Codina 
539*e5116699SHerve Codina 	ret = idt821034_set_gain_channel(idt821034, ch, gain_type,
540*e5116699SHerve Codina 					 is_mute ? 0 : amp->gain);
541*e5116699SHerve Codina 	if (ret)
542*e5116699SHerve Codina 		goto end;
543*e5116699SHerve Codina 
544*e5116699SHerve Codina 	amp->is_muted = is_mute;
545*e5116699SHerve Codina 	ret = 1; /* The value changed */
546*e5116699SHerve Codina end:
547*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
548*e5116699SHerve Codina 	return ret;
549*e5116699SHerve Codina }
550*e5116699SHerve Codina 
551*e5116699SHerve Codina static const DECLARE_TLV_DB_LINEAR(idt821034_gain_in, -6520, 1306);
552*e5116699SHerve Codina #define IDT821034_GAIN_IN_MIN_RAW	1 /* -65.20 dB -> 10^(-65.2/20.0) * 1820 = 1 */
553*e5116699SHerve Codina #define IDT821034_GAIN_IN_MAX_RAW	8191 /* 13.06 dB -> 10^(13.06/20.0) * 1820 = 8191 */
554*e5116699SHerve Codina #define IDT821034_GAIN_IN_INIT_RAW	1820 /* 0dB -> 10^(0/20) * 1820 = 1820 */
555*e5116699SHerve Codina 
556*e5116699SHerve Codina static const DECLARE_TLV_DB_LINEAR(idt821034_gain_out, -6798, 1029);
557*e5116699SHerve Codina #define IDT821034_GAIN_OUT_MIN_RAW	1 /* -67.98 dB -> 10^(-67.98/20.0) * 2506 = 1*/
558*e5116699SHerve Codina #define IDT821034_GAIN_OUT_MAX_RAW	8191 /* 10.29 dB -> 10^(10.29/20.0) * 2506 = 8191 */
559*e5116699SHerve Codina #define IDT821034_GAIN_OUT_INIT_RAW	2506 /* 0dB -> 10^(0/20) * 2506 = 2506 */
560*e5116699SHerve Codina 
561*e5116699SHerve Codina static const struct snd_kcontrol_new idt821034_controls[] = {
562*e5116699SHerve Codina 	/* DAC volume control */
563*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("DAC0 Playback Volume", IDT821034_ID_OUT(0), 0,
564*e5116699SHerve Codina 				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,
565*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
566*e5116699SHerve Codina 				 idt821034_gain_out),
567*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("DAC1 Playback Volume", IDT821034_ID_OUT(1), 0,
568*e5116699SHerve Codina 				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,
569*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
570*e5116699SHerve Codina 				 idt821034_gain_out),
571*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("DAC2 Playback Volume", IDT821034_ID_OUT(2), 0,
572*e5116699SHerve Codina 				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,
573*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
574*e5116699SHerve Codina 				 idt821034_gain_out),
575*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("DAC3 Playback Volume", IDT821034_ID_OUT(3), 0,
576*e5116699SHerve Codina 				 IDT821034_GAIN_OUT_MIN_RAW, IDT821034_GAIN_OUT_MAX_RAW,
577*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
578*e5116699SHerve Codina 				 idt821034_gain_out),
579*e5116699SHerve Codina 
580*e5116699SHerve Codina 	/* DAC mute control */
581*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("DAC0 Playback Switch", IDT821034_ID_OUT(0),
582*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
583*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("DAC1 Playback Switch", IDT821034_ID_OUT(1),
584*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
585*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("DAC2 Playback Switch", IDT821034_ID_OUT(2),
586*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
587*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("DAC3 Playback Switch", IDT821034_ID_OUT(3),
588*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
589*e5116699SHerve Codina 
590*e5116699SHerve Codina 	/* ADC volume control */
591*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("ADC0 Capture Volume", IDT821034_ID_IN(0), 0,
592*e5116699SHerve Codina 				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,
593*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
594*e5116699SHerve Codina 				 idt821034_gain_in),
595*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("ADC1 Capture Volume", IDT821034_ID_IN(1), 0,
596*e5116699SHerve Codina 				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,
597*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
598*e5116699SHerve Codina 				 idt821034_gain_in),
599*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("ADC2 Capture Volume", IDT821034_ID_IN(2), 0,
600*e5116699SHerve Codina 				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,
601*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
602*e5116699SHerve Codina 				 idt821034_gain_in),
603*e5116699SHerve Codina 	SOC_SINGLE_RANGE_EXT_TLV("ADC3 Capture Volume", IDT821034_ID_IN(3), 0,
604*e5116699SHerve Codina 				 IDT821034_GAIN_IN_MIN_RAW, IDT821034_GAIN_IN_MAX_RAW,
605*e5116699SHerve Codina 				 0, idt821034_kctrl_gain_get, idt821034_kctrl_gain_put,
606*e5116699SHerve Codina 				 idt821034_gain_in),
607*e5116699SHerve Codina 
608*e5116699SHerve Codina 	/* ADC mute control */
609*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("ADC0 Capture Switch", IDT821034_ID_IN(0),
610*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
611*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("ADC1 Capture Switch", IDT821034_ID_IN(1),
612*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
613*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("ADC2 Capture Switch", IDT821034_ID_IN(2),
614*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
615*e5116699SHerve Codina 	SOC_SINGLE_BOOL_EXT("ADC3 Capture Switch", IDT821034_ID_IN(3),
616*e5116699SHerve Codina 			    idt821034_kctrl_mute_get, idt821034_kctrl_mute_put),
617*e5116699SHerve Codina };
618*e5116699SHerve Codina 
idt821034_power_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)619*e5116699SHerve Codina static int idt821034_power_event(struct snd_soc_dapm_widget *w,
620*e5116699SHerve Codina 				 struct snd_kcontrol *kcontrol, int event)
621*e5116699SHerve Codina {
622*e5116699SHerve Codina 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
623*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
624*e5116699SHerve Codina 	unsigned int id = w->shift;
625*e5116699SHerve Codina 	u8 power, mask;
626*e5116699SHerve Codina 	int ret;
627*e5116699SHerve Codina 	u8 ch;
628*e5116699SHerve Codina 
629*e5116699SHerve Codina 	ch = IDT821034_ID_GET_CHAN(id);
630*e5116699SHerve Codina 	mask = IDT821034_ID_IS_OUT(id) ? IDT821034_CONF_PWRUP_RX : IDT821034_CONF_PWRUP_TX;
631*e5116699SHerve Codina 
632*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
633*e5116699SHerve Codina 
634*e5116699SHerve Codina 	power = idt821034_get_channel_power(idt821034, ch);
635*e5116699SHerve Codina 	if (SND_SOC_DAPM_EVENT_ON(event))
636*e5116699SHerve Codina 		power |= mask;
637*e5116699SHerve Codina 	else
638*e5116699SHerve Codina 		power &= ~mask;
639*e5116699SHerve Codina 	ret = idt821034_set_channel_power(idt821034, ch, power);
640*e5116699SHerve Codina 
641*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
642*e5116699SHerve Codina 
643*e5116699SHerve Codina 	return ret;
644*e5116699SHerve Codina }
645*e5116699SHerve Codina 
646*e5116699SHerve Codina static const struct snd_soc_dapm_widget idt821034_dapm_widgets[] = {
647*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("DAC0", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(0), 0,
648*e5116699SHerve Codina 			   idt821034_power_event,
649*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
650*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("DAC1", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(1), 0,
651*e5116699SHerve Codina 			   idt821034_power_event,
652*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
653*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("DAC2", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(2), 0,
654*e5116699SHerve Codina 			   idt821034_power_event,
655*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
656*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("DAC3", "Playback", SND_SOC_NOPM, IDT821034_ID_OUT(3), 0,
657*e5116699SHerve Codina 			   idt821034_power_event,
658*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
659*e5116699SHerve Codina 
660*e5116699SHerve Codina 	SND_SOC_DAPM_OUTPUT("OUT0"),
661*e5116699SHerve Codina 	SND_SOC_DAPM_OUTPUT("OUT1"),
662*e5116699SHerve Codina 	SND_SOC_DAPM_OUTPUT("OUT2"),
663*e5116699SHerve Codina 	SND_SOC_DAPM_OUTPUT("OUT3"),
664*e5116699SHerve Codina 
665*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("ADC0", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(0), 0,
666*e5116699SHerve Codina 			   idt821034_power_event,
667*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
668*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("ADC1", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(1), 0,
669*e5116699SHerve Codina 			   idt821034_power_event,
670*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
671*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("ADC2", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(2), 0,
672*e5116699SHerve Codina 			   idt821034_power_event,
673*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
674*e5116699SHerve Codina 	SND_SOC_DAPM_DAC_E("ADC3", "Capture", SND_SOC_NOPM, IDT821034_ID_IN(3), 0,
675*e5116699SHerve Codina 			   idt821034_power_event,
676*e5116699SHerve Codina 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
677*e5116699SHerve Codina 
678*e5116699SHerve Codina 	SND_SOC_DAPM_INPUT("IN0"),
679*e5116699SHerve Codina 	SND_SOC_DAPM_INPUT("IN1"),
680*e5116699SHerve Codina 	SND_SOC_DAPM_INPUT("IN2"),
681*e5116699SHerve Codina 	SND_SOC_DAPM_INPUT("IN3"),
682*e5116699SHerve Codina };
683*e5116699SHerve Codina 
684*e5116699SHerve Codina static const struct snd_soc_dapm_route idt821034_dapm_routes[] = {
685*e5116699SHerve Codina 	{ "OUT0", NULL, "DAC0" },
686*e5116699SHerve Codina 	{ "OUT1", NULL, "DAC1" },
687*e5116699SHerve Codina 	{ "OUT2", NULL, "DAC2" },
688*e5116699SHerve Codina 	{ "OUT3", NULL, "DAC3" },
689*e5116699SHerve Codina 
690*e5116699SHerve Codina 	{ "ADC0", NULL, "IN0" },
691*e5116699SHerve Codina 	{ "ADC1", NULL, "IN1" },
692*e5116699SHerve Codina 	{ "ADC2", NULL, "IN2" },
693*e5116699SHerve Codina 	{ "ADC3", NULL, "IN3" },
694*e5116699SHerve Codina };
695*e5116699SHerve Codina 
idt821034_dai_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int width)696*e5116699SHerve Codina static int idt821034_dai_set_tdm_slot(struct snd_soc_dai *dai,
697*e5116699SHerve Codina 				      unsigned int tx_mask, unsigned int rx_mask,
698*e5116699SHerve Codina 				      int slots, int width)
699*e5116699SHerve Codina {
700*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);
701*e5116699SHerve Codina 	unsigned int mask;
702*e5116699SHerve Codina 	u8 slot;
703*e5116699SHerve Codina 	int ret;
704*e5116699SHerve Codina 	u8 ch;
705*e5116699SHerve Codina 
706*e5116699SHerve Codina 	switch (width) {
707*e5116699SHerve Codina 	case 0: /* Not set -> default 8 */
708*e5116699SHerve Codina 	case 8:
709*e5116699SHerve Codina 		break;
710*e5116699SHerve Codina 	default:
711*e5116699SHerve Codina 		dev_err(dai->dev, "tdm slot width %d not supported\n", width);
712*e5116699SHerve Codina 		return -EINVAL;
713*e5116699SHerve Codina 	}
714*e5116699SHerve Codina 
715*e5116699SHerve Codina 	mask = tx_mask;
716*e5116699SHerve Codina 	slot = 0;
717*e5116699SHerve Codina 	ch = 0;
718*e5116699SHerve Codina 	while (mask && ch < IDT821034_NB_CHANNEL) {
719*e5116699SHerve Codina 		if (mask & 0x1) {
720*e5116699SHerve Codina 			mutex_lock(&idt821034->mutex);
721*e5116699SHerve Codina 			ret = idt821034_set_channel_ts(idt821034, ch, IDT821034_CH_RX, slot);
722*e5116699SHerve Codina 			mutex_unlock(&idt821034->mutex);
723*e5116699SHerve Codina 			if (ret) {
724*e5116699SHerve Codina 				dev_err(dai->dev, "ch%u set tx tdm slot failed (%d)\n",
725*e5116699SHerve Codina 					ch, ret);
726*e5116699SHerve Codina 				return ret;
727*e5116699SHerve Codina 			}
728*e5116699SHerve Codina 			ch++;
729*e5116699SHerve Codina 		}
730*e5116699SHerve Codina 		mask >>= 1;
731*e5116699SHerve Codina 		slot++;
732*e5116699SHerve Codina 	}
733*e5116699SHerve Codina 	if (mask) {
734*e5116699SHerve Codina 		dev_err(dai->dev, "too much tx slots defined (mask = 0x%x) support max %d\n",
735*e5116699SHerve Codina 			tx_mask, IDT821034_NB_CHANNEL);
736*e5116699SHerve Codina 		return -EINVAL;
737*e5116699SHerve Codina 	}
738*e5116699SHerve Codina 	idt821034->max_ch_playback = ch;
739*e5116699SHerve Codina 
740*e5116699SHerve Codina 	mask = rx_mask;
741*e5116699SHerve Codina 	slot = 0;
742*e5116699SHerve Codina 	ch = 0;
743*e5116699SHerve Codina 	while (mask && ch < IDT821034_NB_CHANNEL) {
744*e5116699SHerve Codina 		if (mask & 0x1) {
745*e5116699SHerve Codina 			mutex_lock(&idt821034->mutex);
746*e5116699SHerve Codina 			ret = idt821034_set_channel_ts(idt821034, ch, IDT821034_CH_TX, slot);
747*e5116699SHerve Codina 			mutex_unlock(&idt821034->mutex);
748*e5116699SHerve Codina 			if (ret) {
749*e5116699SHerve Codina 				dev_err(dai->dev, "ch%u set rx tdm slot failed (%d)\n",
750*e5116699SHerve Codina 					ch, ret);
751*e5116699SHerve Codina 				return ret;
752*e5116699SHerve Codina 			}
753*e5116699SHerve Codina 			ch++;
754*e5116699SHerve Codina 		}
755*e5116699SHerve Codina 		mask >>= 1;
756*e5116699SHerve Codina 		slot++;
757*e5116699SHerve Codina 	}
758*e5116699SHerve Codina 	if (mask) {
759*e5116699SHerve Codina 		dev_err(dai->dev, "too much rx slots defined (mask = 0x%x) support max %d\n",
760*e5116699SHerve Codina 			rx_mask, IDT821034_NB_CHANNEL);
761*e5116699SHerve Codina 		return -EINVAL;
762*e5116699SHerve Codina 	}
763*e5116699SHerve Codina 	idt821034->max_ch_capture = ch;
764*e5116699SHerve Codina 
765*e5116699SHerve Codina 	return 0;
766*e5116699SHerve Codina }
767*e5116699SHerve Codina 
idt821034_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)768*e5116699SHerve Codina static int idt821034_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
769*e5116699SHerve Codina {
770*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);
771*e5116699SHerve Codina 	u8 conf;
772*e5116699SHerve Codina 	int ret;
773*e5116699SHerve Codina 
774*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
775*e5116699SHerve Codina 
776*e5116699SHerve Codina 	conf = idt821034_get_codec_conf(idt821034);
777*e5116699SHerve Codina 
778*e5116699SHerve Codina 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
779*e5116699SHerve Codina 	case SND_SOC_DAIFMT_DSP_A:
780*e5116699SHerve Codina 		conf |= IDT821034_CONF_DELAY_MODE;
781*e5116699SHerve Codina 		break;
782*e5116699SHerve Codina 	case SND_SOC_DAIFMT_DSP_B:
783*e5116699SHerve Codina 		conf &= ~IDT821034_CONF_DELAY_MODE;
784*e5116699SHerve Codina 		break;
785*e5116699SHerve Codina 	default:
786*e5116699SHerve Codina 		dev_err(dai->dev, "Unsupported DAI format 0x%x\n",
787*e5116699SHerve Codina 			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
788*e5116699SHerve Codina 		ret = -EINVAL;
789*e5116699SHerve Codina 		goto end;
790*e5116699SHerve Codina 	}
791*e5116699SHerve Codina 	ret = idt821034_set_codec_conf(idt821034, conf);
792*e5116699SHerve Codina end:
793*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
794*e5116699SHerve Codina 	return ret;
795*e5116699SHerve Codina }
796*e5116699SHerve Codina 
idt821034_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)797*e5116699SHerve Codina static int idt821034_dai_hw_params(struct snd_pcm_substream *substream,
798*e5116699SHerve Codina 				   struct snd_pcm_hw_params *params,
799*e5116699SHerve Codina 				   struct snd_soc_dai *dai)
800*e5116699SHerve Codina {
801*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);
802*e5116699SHerve Codina 	u8 conf;
803*e5116699SHerve Codina 	int ret;
804*e5116699SHerve Codina 
805*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
806*e5116699SHerve Codina 
807*e5116699SHerve Codina 	conf = idt821034_get_codec_conf(idt821034);
808*e5116699SHerve Codina 
809*e5116699SHerve Codina 	switch (params_format(params)) {
810*e5116699SHerve Codina 	case SNDRV_PCM_FORMAT_A_LAW:
811*e5116699SHerve Codina 		conf |= IDT821034_CONF_ALAW_MODE;
812*e5116699SHerve Codina 		break;
813*e5116699SHerve Codina 	case SNDRV_PCM_FORMAT_MU_LAW:
814*e5116699SHerve Codina 		conf &= ~IDT821034_CONF_ALAW_MODE;
815*e5116699SHerve Codina 		break;
816*e5116699SHerve Codina 	default:
817*e5116699SHerve Codina 		dev_err(dai->dev, "Unsupported PCM format 0x%x\n",
818*e5116699SHerve Codina 			params_format(params));
819*e5116699SHerve Codina 		ret = -EINVAL;
820*e5116699SHerve Codina 		goto end;
821*e5116699SHerve Codina 	}
822*e5116699SHerve Codina 	ret = idt821034_set_codec_conf(idt821034, conf);
823*e5116699SHerve Codina end:
824*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
825*e5116699SHerve Codina 	return ret;
826*e5116699SHerve Codina }
827*e5116699SHerve Codina 
828*e5116699SHerve Codina static const unsigned int idt821034_sample_bits[] = {8};
829*e5116699SHerve Codina 
830*e5116699SHerve Codina static struct snd_pcm_hw_constraint_list idt821034_sample_bits_constr = {
831*e5116699SHerve Codina 	.list = idt821034_sample_bits,
832*e5116699SHerve Codina 	.count = ARRAY_SIZE(idt821034_sample_bits),
833*e5116699SHerve Codina };
834*e5116699SHerve Codina 
idt821034_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)835*e5116699SHerve Codina static int idt821034_dai_startup(struct snd_pcm_substream *substream,
836*e5116699SHerve Codina 				 struct snd_soc_dai *dai)
837*e5116699SHerve Codina {
838*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(dai->component);
839*e5116699SHerve Codina 	unsigned int max_ch = 0;
840*e5116699SHerve Codina 	int ret;
841*e5116699SHerve Codina 
842*e5116699SHerve Codina 	max_ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
843*e5116699SHerve Codina 		idt821034->max_ch_playback : idt821034->max_ch_capture;
844*e5116699SHerve Codina 
845*e5116699SHerve Codina 	/*
846*e5116699SHerve Codina 	 * Disable stream support (min = 0, max = 0) if no timeslots were
847*e5116699SHerve Codina 	 * configured otherwise, limit the number of channels to those
848*e5116699SHerve Codina 	 * configured.
849*e5116699SHerve Codina 	 */
850*e5116699SHerve Codina 	ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
851*e5116699SHerve Codina 					   max_ch ? 1 : 0, max_ch);
852*e5116699SHerve Codina 	if (ret < 0)
853*e5116699SHerve Codina 		return ret;
854*e5116699SHerve Codina 
855*e5116699SHerve Codina 	ret = snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
856*e5116699SHerve Codina 					 &idt821034_sample_bits_constr);
857*e5116699SHerve Codina 	if (ret)
858*e5116699SHerve Codina 		return ret;
859*e5116699SHerve Codina 
860*e5116699SHerve Codina 	return 0;
861*e5116699SHerve Codina }
862*e5116699SHerve Codina 
863*e5116699SHerve Codina static u64 idt821034_dai_formats[] = {
864*e5116699SHerve Codina 	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|
865*e5116699SHerve Codina 	SND_SOC_POSSIBLE_DAIFMT_DSP_B,
866*e5116699SHerve Codina };
867*e5116699SHerve Codina 
868*e5116699SHerve Codina static const struct snd_soc_dai_ops idt821034_dai_ops = {
869*e5116699SHerve Codina 	.startup      = idt821034_dai_startup,
870*e5116699SHerve Codina 	.hw_params    = idt821034_dai_hw_params,
871*e5116699SHerve Codina 	.set_tdm_slot = idt821034_dai_set_tdm_slot,
872*e5116699SHerve Codina 	.set_fmt      = idt821034_dai_set_fmt,
873*e5116699SHerve Codina 	.auto_selectable_formats     = idt821034_dai_formats,
874*e5116699SHerve Codina 	.num_auto_selectable_formats = ARRAY_SIZE(idt821034_dai_formats),
875*e5116699SHerve Codina };
876*e5116699SHerve Codina 
877*e5116699SHerve Codina static struct snd_soc_dai_driver idt821034_dai_driver = {
878*e5116699SHerve Codina 	.name = "idt821034",
879*e5116699SHerve Codina 	.playback = {
880*e5116699SHerve Codina 		.stream_name = "Playback",
881*e5116699SHerve Codina 		.channels_min = 1,
882*e5116699SHerve Codina 		.channels_max = IDT821034_NB_CHANNEL,
883*e5116699SHerve Codina 		.rates = SNDRV_PCM_RATE_8000,
884*e5116699SHerve Codina 		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
885*e5116699SHerve Codina 	},
886*e5116699SHerve Codina 	.capture = {
887*e5116699SHerve Codina 		.stream_name = "Capture",
888*e5116699SHerve Codina 		.channels_min = 1,
889*e5116699SHerve Codina 		.channels_max = IDT821034_NB_CHANNEL,
890*e5116699SHerve Codina 		.rates = SNDRV_PCM_RATE_8000,
891*e5116699SHerve Codina 		.formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
892*e5116699SHerve Codina 	},
893*e5116699SHerve Codina 	.ops = &idt821034_dai_ops,
894*e5116699SHerve Codina };
895*e5116699SHerve Codina 
idt821034_reset_audio(struct idt821034 * idt821034)896*e5116699SHerve Codina static int idt821034_reset_audio(struct idt821034 *idt821034)
897*e5116699SHerve Codina {
898*e5116699SHerve Codina 	int ret;
899*e5116699SHerve Codina 	u8 i;
900*e5116699SHerve Codina 
901*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
902*e5116699SHerve Codina 
903*e5116699SHerve Codina 	ret = idt821034_set_codec_conf(idt821034, 0);
904*e5116699SHerve Codina 	if (ret)
905*e5116699SHerve Codina 		goto end;
906*e5116699SHerve Codina 
907*e5116699SHerve Codina 	for (i = 0; i < IDT821034_NB_CHANNEL; i++) {
908*e5116699SHerve Codina 		idt821034->amps.ch[i].amp_out.gain = IDT821034_GAIN_OUT_INIT_RAW;
909*e5116699SHerve Codina 		idt821034->amps.ch[i].amp_out.is_muted = false;
910*e5116699SHerve Codina 		ret = idt821034_set_gain_channel(idt821034, i, IDT821034_GAIN_RX,
911*e5116699SHerve Codina 						 idt821034->amps.ch[i].amp_out.gain);
912*e5116699SHerve Codina 		if (ret)
913*e5116699SHerve Codina 			goto end;
914*e5116699SHerve Codina 
915*e5116699SHerve Codina 		idt821034->amps.ch[i].amp_in.gain = IDT821034_GAIN_IN_INIT_RAW;
916*e5116699SHerve Codina 		idt821034->amps.ch[i].amp_in.is_muted = false;
917*e5116699SHerve Codina 		ret = idt821034_set_gain_channel(idt821034, i, IDT821034_GAIN_TX,
918*e5116699SHerve Codina 						 idt821034->amps.ch[i].amp_in.gain);
919*e5116699SHerve Codina 		if (ret)
920*e5116699SHerve Codina 			goto end;
921*e5116699SHerve Codina 
922*e5116699SHerve Codina 		ret = idt821034_set_channel_power(idt821034, i, 0);
923*e5116699SHerve Codina 		if (ret)
924*e5116699SHerve Codina 			goto end;
925*e5116699SHerve Codina 	}
926*e5116699SHerve Codina 
927*e5116699SHerve Codina 	ret = 0;
928*e5116699SHerve Codina end:
929*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
930*e5116699SHerve Codina 	return ret;
931*e5116699SHerve Codina }
932*e5116699SHerve Codina 
idt821034_component_probe(struct snd_soc_component * component)933*e5116699SHerve Codina static int idt821034_component_probe(struct snd_soc_component *component)
934*e5116699SHerve Codina {
935*e5116699SHerve Codina 	struct idt821034 *idt821034 = snd_soc_component_get_drvdata(component);
936*e5116699SHerve Codina 	int ret;
937*e5116699SHerve Codina 
938*e5116699SHerve Codina 	/* reset idt821034 audio part*/
939*e5116699SHerve Codina 	ret = idt821034_reset_audio(idt821034);
940*e5116699SHerve Codina 	if (ret)
941*e5116699SHerve Codina 		return ret;
942*e5116699SHerve Codina 
943*e5116699SHerve Codina 	return 0;
944*e5116699SHerve Codina }
945*e5116699SHerve Codina 
946*e5116699SHerve Codina static const struct snd_soc_component_driver idt821034_component_driver = {
947*e5116699SHerve Codina 	.probe			= idt821034_component_probe,
948*e5116699SHerve Codina 	.controls		= idt821034_controls,
949*e5116699SHerve Codina 	.num_controls		= ARRAY_SIZE(idt821034_controls),
950*e5116699SHerve Codina 	.dapm_widgets		= idt821034_dapm_widgets,
951*e5116699SHerve Codina 	.num_dapm_widgets	= ARRAY_SIZE(idt821034_dapm_widgets),
952*e5116699SHerve Codina 	.dapm_routes		= idt821034_dapm_routes,
953*e5116699SHerve Codina 	.num_dapm_routes	= ARRAY_SIZE(idt821034_dapm_routes),
954*e5116699SHerve Codina 	.endianness		= 1,
955*e5116699SHerve Codina };
956*e5116699SHerve Codina 
957*e5116699SHerve Codina #define IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(_offset) (((_offset) / 5) % 4)
958*e5116699SHerve Codina #define IDT821034_GPIO_OFFSET_TO_SLIC_MASK(_offset)    BIT((_offset) % 5)
959*e5116699SHerve Codina 
idt821034_chip_gpio_set(struct gpio_chip * c,unsigned int offset,int val)960*e5116699SHerve Codina static void idt821034_chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val)
961*e5116699SHerve Codina {
962*e5116699SHerve Codina 	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);
963*e5116699SHerve Codina 	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);
964*e5116699SHerve Codina 	struct idt821034 *idt821034 = gpiochip_get_data(c);
965*e5116699SHerve Codina 	u8 slic_raw;
966*e5116699SHerve Codina 	int ret;
967*e5116699SHerve Codina 
968*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
969*e5116699SHerve Codina 
970*e5116699SHerve Codina 	slic_raw = idt821034_get_written_slic_raw(idt821034, ch);
971*e5116699SHerve Codina 	if (val)
972*e5116699SHerve Codina 		slic_raw |= mask;
973*e5116699SHerve Codina 	else
974*e5116699SHerve Codina 		slic_raw &= ~mask;
975*e5116699SHerve Codina 	ret = idt821034_write_slic_raw(idt821034, ch, slic_raw);
976*e5116699SHerve Codina 	if (ret) {
977*e5116699SHerve Codina 		dev_err(&idt821034->spi->dev, "set gpio %d (%u, 0x%x) failed (%d)\n",
978*e5116699SHerve Codina 			offset, ch, mask, ret);
979*e5116699SHerve Codina 	}
980*e5116699SHerve Codina 
981*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
982*e5116699SHerve Codina }
983*e5116699SHerve Codina 
idt821034_chip_gpio_get(struct gpio_chip * c,unsigned int offset)984*e5116699SHerve Codina static int idt821034_chip_gpio_get(struct gpio_chip *c, unsigned int offset)
985*e5116699SHerve Codina {
986*e5116699SHerve Codina 	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);
987*e5116699SHerve Codina 	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);
988*e5116699SHerve Codina 	struct idt821034 *idt821034 = gpiochip_get_data(c);
989*e5116699SHerve Codina 	u8 slic_raw;
990*e5116699SHerve Codina 	int ret;
991*e5116699SHerve Codina 
992*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
993*e5116699SHerve Codina 	ret = idt821034_read_slic_raw(idt821034, ch, &slic_raw);
994*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
995*e5116699SHerve Codina 	if (ret) {
996*e5116699SHerve Codina 		dev_err(&idt821034->spi->dev, "get gpio %d (%u, 0x%x) failed (%d)\n",
997*e5116699SHerve Codina 			offset, ch, mask, ret);
998*e5116699SHerve Codina 		return ret;
999*e5116699SHerve Codina 	}
1000*e5116699SHerve Codina 
1001*e5116699SHerve Codina 	/*
1002*e5116699SHerve Codina 	 * SLIC IOs are read in reverse order compared to write.
1003*e5116699SHerve Codina 	 * Reverse the read value here in order to have IO0 at lsb (ie same
1004*e5116699SHerve Codina 	 * order as write)
1005*e5116699SHerve Codina 	 */
1006*e5116699SHerve Codina 	return !!(bitrev8(slic_raw) & mask);
1007*e5116699SHerve Codina }
1008*e5116699SHerve Codina 
idt821034_chip_get_direction(struct gpio_chip * c,unsigned int offset)1009*e5116699SHerve Codina static int idt821034_chip_get_direction(struct gpio_chip *c, unsigned int offset)
1010*e5116699SHerve Codina {
1011*e5116699SHerve Codina 	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);
1012*e5116699SHerve Codina 	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);
1013*e5116699SHerve Codina 	struct idt821034 *idt821034 = gpiochip_get_data(c);
1014*e5116699SHerve Codina 	u8 slic_dir;
1015*e5116699SHerve Codina 
1016*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
1017*e5116699SHerve Codina 	slic_dir = idt821034_get_slic_conf(idt821034, ch);
1018*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
1019*e5116699SHerve Codina 
1020*e5116699SHerve Codina 	return slic_dir & mask ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
1021*e5116699SHerve Codina }
1022*e5116699SHerve Codina 
idt821034_chip_direction_input(struct gpio_chip * c,unsigned int offset)1023*e5116699SHerve Codina static int idt821034_chip_direction_input(struct gpio_chip *c, unsigned int offset)
1024*e5116699SHerve Codina {
1025*e5116699SHerve Codina 	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);
1026*e5116699SHerve Codina 	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);
1027*e5116699SHerve Codina 	struct idt821034 *idt821034 = gpiochip_get_data(c);
1028*e5116699SHerve Codina 	u8 slic_conf;
1029*e5116699SHerve Codina 	int ret;
1030*e5116699SHerve Codina 
1031*e5116699SHerve Codina 	/* Only IO0 and IO1 can be set as input */
1032*e5116699SHerve Codina 	if (mask & ~(IDT821034_SLIC_IO1_IN | IDT821034_SLIC_IO0_IN))
1033*e5116699SHerve Codina 		return -EPERM;
1034*e5116699SHerve Codina 
1035*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
1036*e5116699SHerve Codina 
1037*e5116699SHerve Codina 	slic_conf = idt821034_get_slic_conf(idt821034, ch) | mask;
1038*e5116699SHerve Codina 
1039*e5116699SHerve Codina 	ret = idt821034_set_slic_conf(idt821034, ch, slic_conf);
1040*e5116699SHerve Codina 	if (ret) {
1041*e5116699SHerve Codina 		dev_err(&idt821034->spi->dev, "dir in gpio %d (%u, 0x%x) failed (%d)\n",
1042*e5116699SHerve Codina 			offset, ch, mask, ret);
1043*e5116699SHerve Codina 	}
1044*e5116699SHerve Codina 
1045*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
1046*e5116699SHerve Codina 	return ret;
1047*e5116699SHerve Codina }
1048*e5116699SHerve Codina 
idt821034_chip_direction_output(struct gpio_chip * c,unsigned int offset,int val)1049*e5116699SHerve Codina static int idt821034_chip_direction_output(struct gpio_chip *c, unsigned int offset, int val)
1050*e5116699SHerve Codina {
1051*e5116699SHerve Codina 	u8 ch = IDT821034_GPIO_OFFSET_TO_SLIC_CHANNEL(offset);
1052*e5116699SHerve Codina 	u8 mask = IDT821034_GPIO_OFFSET_TO_SLIC_MASK(offset);
1053*e5116699SHerve Codina 	struct idt821034 *idt821034 = gpiochip_get_data(c);
1054*e5116699SHerve Codina 	u8 slic_conf;
1055*e5116699SHerve Codina 	int ret;
1056*e5116699SHerve Codina 
1057*e5116699SHerve Codina 	idt821034_chip_gpio_set(c, offset, val);
1058*e5116699SHerve Codina 
1059*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
1060*e5116699SHerve Codina 
1061*e5116699SHerve Codina 	slic_conf = idt821034_get_slic_conf(idt821034, ch) & ~mask;
1062*e5116699SHerve Codina 
1063*e5116699SHerve Codina 	ret = idt821034_set_slic_conf(idt821034, ch, slic_conf);
1064*e5116699SHerve Codina 	if (ret) {
1065*e5116699SHerve Codina 		dev_err(&idt821034->spi->dev, "dir in gpio %d (%u, 0x%x) failed (%d)\n",
1066*e5116699SHerve Codina 			offset, ch, mask, ret);
1067*e5116699SHerve Codina 	}
1068*e5116699SHerve Codina 
1069*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
1070*e5116699SHerve Codina 	return ret;
1071*e5116699SHerve Codina }
1072*e5116699SHerve Codina 
idt821034_reset_gpio(struct idt821034 * idt821034)1073*e5116699SHerve Codina static int idt821034_reset_gpio(struct idt821034 *idt821034)
1074*e5116699SHerve Codina {
1075*e5116699SHerve Codina 	int ret;
1076*e5116699SHerve Codina 	u8 i;
1077*e5116699SHerve Codina 
1078*e5116699SHerve Codina 	mutex_lock(&idt821034->mutex);
1079*e5116699SHerve Codina 
1080*e5116699SHerve Codina 	/* IO0 and IO1 as input for all channels and output IO set to 0 */
1081*e5116699SHerve Codina 	for (i = 0; i < IDT821034_NB_CHANNEL; i++) {
1082*e5116699SHerve Codina 		ret = idt821034_set_slic_conf(idt821034, i,
1083*e5116699SHerve Codina 					      IDT821034_SLIC_IO1_IN | IDT821034_SLIC_IO0_IN);
1084*e5116699SHerve Codina 		if (ret)
1085*e5116699SHerve Codina 			goto end;
1086*e5116699SHerve Codina 
1087*e5116699SHerve Codina 		ret = idt821034_write_slic_raw(idt821034, i, 0);
1088*e5116699SHerve Codina 		if (ret)
1089*e5116699SHerve Codina 			goto end;
1090*e5116699SHerve Codina 
1091*e5116699SHerve Codina 	}
1092*e5116699SHerve Codina 	ret = 0;
1093*e5116699SHerve Codina end:
1094*e5116699SHerve Codina 	mutex_unlock(&idt821034->mutex);
1095*e5116699SHerve Codina 	return ret;
1096*e5116699SHerve Codina }
1097*e5116699SHerve Codina 
idt821034_gpio_init(struct idt821034 * idt821034)1098*e5116699SHerve Codina static int idt821034_gpio_init(struct idt821034 *idt821034)
1099*e5116699SHerve Codina {
1100*e5116699SHerve Codina 	int ret;
1101*e5116699SHerve Codina 
1102*e5116699SHerve Codina 	ret = idt821034_reset_gpio(idt821034);
1103*e5116699SHerve Codina 	if (ret)
1104*e5116699SHerve Codina 		return ret;
1105*e5116699SHerve Codina 
1106*e5116699SHerve Codina 	idt821034->gpio_chip.owner = THIS_MODULE;
1107*e5116699SHerve Codina 	idt821034->gpio_chip.label = dev_name(&idt821034->spi->dev);
1108*e5116699SHerve Codina 	idt821034->gpio_chip.parent = &idt821034->spi->dev;
1109*e5116699SHerve Codina 	idt821034->gpio_chip.base = -1;
1110*e5116699SHerve Codina 	idt821034->gpio_chip.ngpio = 5 * 4; /* 5 GPIOs on 4 channels */
1111*e5116699SHerve Codina 	idt821034->gpio_chip.get_direction = idt821034_chip_get_direction;
1112*e5116699SHerve Codina 	idt821034->gpio_chip.direction_input = idt821034_chip_direction_input;
1113*e5116699SHerve Codina 	idt821034->gpio_chip.direction_output = idt821034_chip_direction_output;
1114*e5116699SHerve Codina 	idt821034->gpio_chip.get = idt821034_chip_gpio_get;
1115*e5116699SHerve Codina 	idt821034->gpio_chip.set = idt821034_chip_gpio_set;
1116*e5116699SHerve Codina 	idt821034->gpio_chip.can_sleep = true;
1117*e5116699SHerve Codina 
1118*e5116699SHerve Codina 	return devm_gpiochip_add_data(&idt821034->spi->dev, &idt821034->gpio_chip,
1119*e5116699SHerve Codina 				      idt821034);
1120*e5116699SHerve Codina }
1121*e5116699SHerve Codina 
idt821034_spi_probe(struct spi_device * spi)1122*e5116699SHerve Codina static int idt821034_spi_probe(struct spi_device *spi)
1123*e5116699SHerve Codina {
1124*e5116699SHerve Codina 	struct idt821034 *idt821034;
1125*e5116699SHerve Codina 	int ret;
1126*e5116699SHerve Codina 
1127*e5116699SHerve Codina 	spi->bits_per_word = 8;
1128*e5116699SHerve Codina 	ret = spi_setup(spi);
1129*e5116699SHerve Codina 	if (ret < 0)
1130*e5116699SHerve Codina 		return ret;
1131*e5116699SHerve Codina 
1132*e5116699SHerve Codina 	idt821034 = devm_kzalloc(&spi->dev, sizeof(*idt821034), GFP_KERNEL);
1133*e5116699SHerve Codina 	if (!idt821034)
1134*e5116699SHerve Codina 		return -ENOMEM;
1135*e5116699SHerve Codina 
1136*e5116699SHerve Codina 	idt821034->spi = spi;
1137*e5116699SHerve Codina 
1138*e5116699SHerve Codina 	mutex_init(&idt821034->mutex);
1139*e5116699SHerve Codina 
1140*e5116699SHerve Codina 	spi_set_drvdata(spi, idt821034);
1141*e5116699SHerve Codina 
1142*e5116699SHerve Codina 	ret = devm_snd_soc_register_component(&spi->dev, &idt821034_component_driver,
1143*e5116699SHerve Codina 					      &idt821034_dai_driver, 1);
1144*e5116699SHerve Codina 	if (ret)
1145*e5116699SHerve Codina 		return ret;
1146*e5116699SHerve Codina 
1147*e5116699SHerve Codina 	if (IS_ENABLED(CONFIG_GPIOLIB))
1148*e5116699SHerve Codina 		return idt821034_gpio_init(idt821034);
1149*e5116699SHerve Codina 
1150*e5116699SHerve Codina 	return 0;
1151*e5116699SHerve Codina }
1152*e5116699SHerve Codina 
1153*e5116699SHerve Codina static const struct of_device_id idt821034_of_match[] = {
1154*e5116699SHerve Codina 	{ .compatible = "renesas,idt821034", },
1155*e5116699SHerve Codina 	{ }
1156*e5116699SHerve Codina };
1157*e5116699SHerve Codina MODULE_DEVICE_TABLE(of, idt821034_of_match);
1158*e5116699SHerve Codina 
1159*e5116699SHerve Codina static const struct spi_device_id idt821034_id_table[] = {
1160*e5116699SHerve Codina 	{ "idt821034", 0 },
1161*e5116699SHerve Codina 	{ }
1162*e5116699SHerve Codina };
1163*e5116699SHerve Codina MODULE_DEVICE_TABLE(spi, idt821034_id_table);
1164*e5116699SHerve Codina 
1165*e5116699SHerve Codina static struct spi_driver idt821034_spi_driver = {
1166*e5116699SHerve Codina 	.driver  = {
1167*e5116699SHerve Codina 		.name   = "idt821034",
1168*e5116699SHerve Codina 		.of_match_table = idt821034_of_match,
1169*e5116699SHerve Codina 	},
1170*e5116699SHerve Codina 	.id_table = idt821034_id_table,
1171*e5116699SHerve Codina 	.probe  = idt821034_spi_probe,
1172*e5116699SHerve Codina };
1173*e5116699SHerve Codina 
1174*e5116699SHerve Codina module_spi_driver(idt821034_spi_driver);
1175*e5116699SHerve Codina 
1176*e5116699SHerve Codina MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
1177*e5116699SHerve Codina MODULE_DESCRIPTION("IDT821034 ALSA SoC driver");
1178*e5116699SHerve Codina MODULE_LICENSE("GPL");
1179