xref: /openbmc/linux/sound/soc/codecs/tscs42xx.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1ba6c2959SSteven Eckhoff // SPDX-License-Identifier: GPL-2.0
2ba6c2959SSteven Eckhoff // tscs42xx.c -- TSCS42xx ALSA SoC Audio driver
3ba6c2959SSteven Eckhoff // Copyright 2017 Tempo Semiconductor, Inc.
4ba6c2959SSteven Eckhoff // Author: Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
5ba6c2959SSteven Eckhoff 
6641eea3fSSteven Eckhoff #include <linux/kernel.h>
7641eea3fSSteven Eckhoff #include <linux/device.h>
8ba6c2959SSteven Eckhoff #include <linux/regmap.h>
9641eea3fSSteven Eckhoff #include <linux/i2c.h>
10641eea3fSSteven Eckhoff #include <linux/err.h>
11641eea3fSSteven Eckhoff #include <linux/string.h>
12641eea3fSSteven Eckhoff #include <linux/module.h>
13641eea3fSSteven Eckhoff #include <linux/delay.h>
14641eea3fSSteven Eckhoff #include <linux/mutex.h>
15aa0f18d7SSteven Eckhoff #include <linux/clk.h>
16641eea3fSSteven Eckhoff #include <sound/tlv.h>
17ba6c2959SSteven Eckhoff #include <sound/pcm_params.h>
18ba6c2959SSteven Eckhoff #include <sound/soc.h>
19ba6c2959SSteven Eckhoff #include <sound/soc-dapm.h>
20ba6c2959SSteven Eckhoff 
21ba6c2959SSteven Eckhoff #include "tscs42xx.h"
22ba6c2959SSteven Eckhoff 
23ba6c2959SSteven Eckhoff #define COEFF_SIZE 3
24ba6c2959SSteven Eckhoff #define BIQUAD_COEFF_COUNT 5
25ba6c2959SSteven Eckhoff #define BIQUAD_SIZE (COEFF_SIZE * BIQUAD_COEFF_COUNT)
26ba6c2959SSteven Eckhoff 
27ba6c2959SSteven Eckhoff #define COEFF_RAM_MAX_ADDR 0xcd
28ba6c2959SSteven Eckhoff #define COEFF_RAM_COEFF_COUNT (COEFF_RAM_MAX_ADDR + 1)
29ba6c2959SSteven Eckhoff #define COEFF_RAM_SIZE (COEFF_SIZE * COEFF_RAM_COEFF_COUNT)
30ba6c2959SSteven Eckhoff 
31ba6c2959SSteven Eckhoff struct tscs42xx {
32ba6c2959SSteven Eckhoff 
33ba6c2959SSteven Eckhoff 	int bclk_ratio;
34ba6c2959SSteven Eckhoff 	int samplerate;
35ba6c2959SSteven Eckhoff 	struct mutex audio_params_lock;
36ba6c2959SSteven Eckhoff 
37ba6c2959SSteven Eckhoff 	u8 coeff_ram[COEFF_RAM_SIZE];
38ba6c2959SSteven Eckhoff 	bool coeff_ram_synced;
39ba6c2959SSteven Eckhoff 	struct mutex coeff_ram_lock;
40ba6c2959SSteven Eckhoff 
41ba6c2959SSteven Eckhoff 	struct mutex pll_lock;
42ba6c2959SSteven Eckhoff 
43ba6c2959SSteven Eckhoff 	struct regmap *regmap;
44aa0f18d7SSteven Eckhoff 
45aa0f18d7SSteven Eckhoff 	struct clk *sysclk;
46aa0f18d7SSteven Eckhoff 	int sysclk_src_id;
47ba6c2959SSteven Eckhoff };
48ba6c2959SSteven Eckhoff 
49ba6c2959SSteven Eckhoff struct coeff_ram_ctl {
50ba6c2959SSteven Eckhoff 	unsigned int addr;
51ba6c2959SSteven Eckhoff 	struct soc_bytes_ext bytes_ext;
52ba6c2959SSteven Eckhoff };
53ba6c2959SSteven Eckhoff 
tscs42xx_volatile(struct device * dev,unsigned int reg)54ba6c2959SSteven Eckhoff static bool tscs42xx_volatile(struct device *dev, unsigned int reg)
55ba6c2959SSteven Eckhoff {
56ba6c2959SSteven Eckhoff 	switch (reg) {
57ba6c2959SSteven Eckhoff 	case R_DACCRWRL:
58ba6c2959SSteven Eckhoff 	case R_DACCRWRM:
59ba6c2959SSteven Eckhoff 	case R_DACCRWRH:
60ba6c2959SSteven Eckhoff 	case R_DACCRRDL:
61ba6c2959SSteven Eckhoff 	case R_DACCRRDM:
62ba6c2959SSteven Eckhoff 	case R_DACCRRDH:
63ba6c2959SSteven Eckhoff 	case R_DACCRSTAT:
64ba6c2959SSteven Eckhoff 	case R_DACCRADDR:
65ba6c2959SSteven Eckhoff 	case R_PLLCTL0:
66ba6c2959SSteven Eckhoff 		return true;
67ba6c2959SSteven Eckhoff 	default:
68ba6c2959SSteven Eckhoff 		return false;
6932c5dca1STom Rix 	}
70ba6c2959SSteven Eckhoff }
71ba6c2959SSteven Eckhoff 
tscs42xx_precious(struct device * dev,unsigned int reg)72ba6c2959SSteven Eckhoff static bool tscs42xx_precious(struct device *dev, unsigned int reg)
73ba6c2959SSteven Eckhoff {
74ba6c2959SSteven Eckhoff 	switch (reg) {
75ba6c2959SSteven Eckhoff 	case R_DACCRWRL:
76ba6c2959SSteven Eckhoff 	case R_DACCRWRM:
77ba6c2959SSteven Eckhoff 	case R_DACCRWRH:
78ba6c2959SSteven Eckhoff 	case R_DACCRRDL:
79ba6c2959SSteven Eckhoff 	case R_DACCRRDM:
80ba6c2959SSteven Eckhoff 	case R_DACCRRDH:
81ba6c2959SSteven Eckhoff 		return true;
82ba6c2959SSteven Eckhoff 	default:
83ba6c2959SSteven Eckhoff 		return false;
8432c5dca1STom Rix 	}
85ba6c2959SSteven Eckhoff }
86ba6c2959SSteven Eckhoff 
87ba6c2959SSteven Eckhoff static const struct regmap_config tscs42xx_regmap = {
88ba6c2959SSteven Eckhoff 	.reg_bits = 8,
89ba6c2959SSteven Eckhoff 	.val_bits = 8,
90ba6c2959SSteven Eckhoff 
91ba6c2959SSteven Eckhoff 	.volatile_reg = tscs42xx_volatile,
92ba6c2959SSteven Eckhoff 	.precious_reg = tscs42xx_precious,
93ba6c2959SSteven Eckhoff 	.max_register = R_DACMBCREL3H,
94ba6c2959SSteven Eckhoff 
95ba6c2959SSteven Eckhoff 	.cache_type = REGCACHE_RBTREE,
96ba6c2959SSteven Eckhoff 	.can_multi_write = true,
97ba6c2959SSteven Eckhoff };
98ba6c2959SSteven Eckhoff 
99ba6c2959SSteven Eckhoff #define MAX_PLL_LOCK_20MS_WAITS 1
plls_locked(struct snd_soc_component * component)1004e46c228SKuninori Morimoto static bool plls_locked(struct snd_soc_component *component)
101ba6c2959SSteven Eckhoff {
102ba6c2959SSteven Eckhoff 	int ret;
103ba6c2959SSteven Eckhoff 	int count = MAX_PLL_LOCK_20MS_WAITS;
104ba6c2959SSteven Eckhoff 
105ba6c2959SSteven Eckhoff 	do {
106981abdfeSKuninori Morimoto 		ret = snd_soc_component_read(component, R_PLLCTL0);
107ba6c2959SSteven Eckhoff 		if (ret < 0) {
1084e46c228SKuninori Morimoto 			dev_err(component->dev,
109ba6c2959SSteven Eckhoff 				"Failed to read PLL lock status (%d)\n", ret);
110ba6c2959SSteven Eckhoff 			return false;
111ba6c2959SSteven Eckhoff 		} else if (ret > 0) {
112ba6c2959SSteven Eckhoff 			return true;
113ba6c2959SSteven Eckhoff 		}
114ba6c2959SSteven Eckhoff 		msleep(20);
115ba6c2959SSteven Eckhoff 	} while (count--);
116ba6c2959SSteven Eckhoff 
117ba6c2959SSteven Eckhoff 	return false;
118ba6c2959SSteven Eckhoff }
119ba6c2959SSteven Eckhoff 
sample_rate_to_pll_freq_out(int sample_rate)120ba6c2959SSteven Eckhoff static int sample_rate_to_pll_freq_out(int sample_rate)
121ba6c2959SSteven Eckhoff {
122ba6c2959SSteven Eckhoff 	switch (sample_rate) {
123ba6c2959SSteven Eckhoff 	case 11025:
124ba6c2959SSteven Eckhoff 	case 22050:
125ba6c2959SSteven Eckhoff 	case 44100:
126ba6c2959SSteven Eckhoff 	case 88200:
127ba6c2959SSteven Eckhoff 		return 112896000;
128ba6c2959SSteven Eckhoff 	case 8000:
129ba6c2959SSteven Eckhoff 	case 16000:
130ba6c2959SSteven Eckhoff 	case 32000:
131ba6c2959SSteven Eckhoff 	case 48000:
132ba6c2959SSteven Eckhoff 	case 96000:
133ba6c2959SSteven Eckhoff 		return 122880000;
134ba6c2959SSteven Eckhoff 	default:
135ba6c2959SSteven Eckhoff 		return -EINVAL;
136ba6c2959SSteven Eckhoff 	}
137ba6c2959SSteven Eckhoff }
138ba6c2959SSteven Eckhoff 
139ba6c2959SSteven Eckhoff #define DACCRSTAT_MAX_TRYS 10
write_coeff_ram(struct snd_soc_component * component,u8 * coeff_ram,unsigned int addr,unsigned int coeff_cnt)1404e46c228SKuninori Morimoto static int write_coeff_ram(struct snd_soc_component *component, u8 *coeff_ram,
141ba6c2959SSteven Eckhoff 	unsigned int addr, unsigned int coeff_cnt)
142ba6c2959SSteven Eckhoff {
1434e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
144ba6c2959SSteven Eckhoff 	int cnt;
145ba6c2959SSteven Eckhoff 	int trys;
146ba6c2959SSteven Eckhoff 	int ret;
147ba6c2959SSteven Eckhoff 
148ba6c2959SSteven Eckhoff 	for (cnt = 0; cnt < coeff_cnt; cnt++, addr++) {
149ba6c2959SSteven Eckhoff 
150ba6c2959SSteven Eckhoff 		for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) {
151981abdfeSKuninori Morimoto 			ret = snd_soc_component_read(component, R_DACCRSTAT);
152ba6c2959SSteven Eckhoff 			if (ret < 0) {
1534e46c228SKuninori Morimoto 				dev_err(component->dev,
154ba6c2959SSteven Eckhoff 					"Failed to read stat (%d)\n", ret);
155ba6c2959SSteven Eckhoff 				return ret;
156ba6c2959SSteven Eckhoff 			}
157ba6c2959SSteven Eckhoff 			if (!ret)
158ba6c2959SSteven Eckhoff 				break;
159ba6c2959SSteven Eckhoff 		}
160ba6c2959SSteven Eckhoff 
161ba6c2959SSteven Eckhoff 		if (trys == DACCRSTAT_MAX_TRYS) {
162ba6c2959SSteven Eckhoff 			ret = -EIO;
1634e46c228SKuninori Morimoto 			dev_err(component->dev,
164ba6c2959SSteven Eckhoff 				"dac coefficient write error (%d)\n", ret);
165ba6c2959SSteven Eckhoff 			return ret;
166ba6c2959SSteven Eckhoff 		}
167ba6c2959SSteven Eckhoff 
168ba6c2959SSteven Eckhoff 		ret = regmap_write(tscs42xx->regmap, R_DACCRADDR, addr);
169ba6c2959SSteven Eckhoff 		if (ret < 0) {
1704e46c228SKuninori Morimoto 			dev_err(component->dev,
171ba6c2959SSteven Eckhoff 				"Failed to write dac ram address (%d)\n", ret);
172ba6c2959SSteven Eckhoff 			return ret;
173ba6c2959SSteven Eckhoff 		}
174ba6c2959SSteven Eckhoff 
175ba6c2959SSteven Eckhoff 		ret = regmap_bulk_write(tscs42xx->regmap, R_DACCRWRL,
176ba6c2959SSteven Eckhoff 			&coeff_ram[addr * COEFF_SIZE],
177ba6c2959SSteven Eckhoff 			COEFF_SIZE);
178ba6c2959SSteven Eckhoff 		if (ret < 0) {
1794e46c228SKuninori Morimoto 			dev_err(component->dev,
180ba6c2959SSteven Eckhoff 				"Failed to write dac ram (%d)\n", ret);
181ba6c2959SSteven Eckhoff 			return ret;
182ba6c2959SSteven Eckhoff 		}
183ba6c2959SSteven Eckhoff 	}
184ba6c2959SSteven Eckhoff 
185ba6c2959SSteven Eckhoff 	return 0;
186ba6c2959SSteven Eckhoff }
187ba6c2959SSteven Eckhoff 
power_up_audio_plls(struct snd_soc_component * component)1884e46c228SKuninori Morimoto static int power_up_audio_plls(struct snd_soc_component *component)
189ba6c2959SSteven Eckhoff {
1904e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
191ba6c2959SSteven Eckhoff 	int freq_out;
192ba6c2959SSteven Eckhoff 	int ret;
193ba6c2959SSteven Eckhoff 	unsigned int mask;
194ba6c2959SSteven Eckhoff 	unsigned int val;
195ba6c2959SSteven Eckhoff 
196ba6c2959SSteven Eckhoff 	freq_out = sample_rate_to_pll_freq_out(tscs42xx->samplerate);
197ba6c2959SSteven Eckhoff 	switch (freq_out) {
198ba6c2959SSteven Eckhoff 	case 122880000: /* 48k */
199ba6c2959SSteven Eckhoff 		mask = RM_PLLCTL1C_PDB_PLL1;
200ba6c2959SSteven Eckhoff 		val = RV_PLLCTL1C_PDB_PLL1_ENABLE;
201ba6c2959SSteven Eckhoff 		break;
202ba6c2959SSteven Eckhoff 	case 112896000: /* 44.1k */
203ba6c2959SSteven Eckhoff 		mask = RM_PLLCTL1C_PDB_PLL2;
204ba6c2959SSteven Eckhoff 		val = RV_PLLCTL1C_PDB_PLL2_ENABLE;
205ba6c2959SSteven Eckhoff 		break;
206ba6c2959SSteven Eckhoff 	default:
207ba6c2959SSteven Eckhoff 		ret = -EINVAL;
2084c4825aeSSteven Eckhoff 		dev_err(component->dev,
2094c4825aeSSteven Eckhoff 				"Unrecognized PLL output freq (%d)\n", ret);
210ba6c2959SSteven Eckhoff 		return ret;
211ba6c2959SSteven Eckhoff 	}
212ba6c2959SSteven Eckhoff 
213ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->pll_lock);
214ba6c2959SSteven Eckhoff 
2154e46c228SKuninori Morimoto 	ret = snd_soc_component_update_bits(component, R_PLLCTL1C, mask, val);
216ba6c2959SSteven Eckhoff 	if (ret < 0) {
2174e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to turn PLL on (%d)\n", ret);
218ba6c2959SSteven Eckhoff 		goto exit;
219ba6c2959SSteven Eckhoff 	}
220ba6c2959SSteven Eckhoff 
2214e46c228SKuninori Morimoto 	if (!plls_locked(component)) {
2224e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to lock plls\n");
223ba6c2959SSteven Eckhoff 		ret = -ENOMSG;
224ba6c2959SSteven Eckhoff 		goto exit;
225ba6c2959SSteven Eckhoff 	}
226ba6c2959SSteven Eckhoff 
227ba6c2959SSteven Eckhoff 	ret = 0;
228ba6c2959SSteven Eckhoff exit:
229ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->pll_lock);
230ba6c2959SSteven Eckhoff 
231ba6c2959SSteven Eckhoff 	return ret;
232ba6c2959SSteven Eckhoff }
233ba6c2959SSteven Eckhoff 
power_down_audio_plls(struct snd_soc_component * component)2344e46c228SKuninori Morimoto static int power_down_audio_plls(struct snd_soc_component *component)
235ba6c2959SSteven Eckhoff {
2364e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
237ba6c2959SSteven Eckhoff 	int ret;
238ba6c2959SSteven Eckhoff 
239ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->pll_lock);
240ba6c2959SSteven Eckhoff 
2414e46c228SKuninori Morimoto 	ret = snd_soc_component_update_bits(component, R_PLLCTL1C,
242ba6c2959SSteven Eckhoff 			RM_PLLCTL1C_PDB_PLL1,
243ba6c2959SSteven Eckhoff 			RV_PLLCTL1C_PDB_PLL1_DISABLE);
244ba6c2959SSteven Eckhoff 	if (ret < 0) {
2454e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to turn PLL off (%d)\n", ret);
246ba6c2959SSteven Eckhoff 		goto exit;
247ba6c2959SSteven Eckhoff 	}
2484e46c228SKuninori Morimoto 	ret = snd_soc_component_update_bits(component, R_PLLCTL1C,
249ba6c2959SSteven Eckhoff 			RM_PLLCTL1C_PDB_PLL2,
250ba6c2959SSteven Eckhoff 			RV_PLLCTL1C_PDB_PLL2_DISABLE);
251ba6c2959SSteven Eckhoff 	if (ret < 0) {
2524e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to turn PLL off (%d)\n", ret);
253ba6c2959SSteven Eckhoff 		goto exit;
254ba6c2959SSteven Eckhoff 	}
255ba6c2959SSteven Eckhoff 
256ba6c2959SSteven Eckhoff 	ret = 0;
257ba6c2959SSteven Eckhoff exit:
258ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->pll_lock);
259ba6c2959SSteven Eckhoff 
260ba6c2959SSteven Eckhoff 	return ret;
261ba6c2959SSteven Eckhoff }
262ba6c2959SSteven Eckhoff 
coeff_ram_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)263ba6c2959SSteven Eckhoff static int coeff_ram_get(struct snd_kcontrol *kcontrol,
264ba6c2959SSteven Eckhoff 	struct snd_ctl_elem_value *ucontrol)
265ba6c2959SSteven Eckhoff {
2664c4825aeSSteven Eckhoff 	struct snd_soc_component *component =
2674c4825aeSSteven Eckhoff 		snd_soc_kcontrol_component(kcontrol);
2684e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
269ba6c2959SSteven Eckhoff 	struct coeff_ram_ctl *ctl =
270ba6c2959SSteven Eckhoff 		(struct coeff_ram_ctl *)kcontrol->private_value;
271ba6c2959SSteven Eckhoff 	struct soc_bytes_ext *params = &ctl->bytes_ext;
272ba6c2959SSteven Eckhoff 
273ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->coeff_ram_lock);
274ba6c2959SSteven Eckhoff 
275ba6c2959SSteven Eckhoff 	memcpy(ucontrol->value.bytes.data,
276ba6c2959SSteven Eckhoff 		&tscs42xx->coeff_ram[ctl->addr * COEFF_SIZE], params->max);
277ba6c2959SSteven Eckhoff 
278ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->coeff_ram_lock);
279ba6c2959SSteven Eckhoff 
280ba6c2959SSteven Eckhoff 	return 0;
281ba6c2959SSteven Eckhoff }
282ba6c2959SSteven Eckhoff 
coeff_ram_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)283ba6c2959SSteven Eckhoff static int coeff_ram_put(struct snd_kcontrol *kcontrol,
284ba6c2959SSteven Eckhoff 	struct snd_ctl_elem_value *ucontrol)
285ba6c2959SSteven Eckhoff {
2864c4825aeSSteven Eckhoff 	struct snd_soc_component *component =
2874c4825aeSSteven Eckhoff 		snd_soc_kcontrol_component(kcontrol);
2884e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
289ba6c2959SSteven Eckhoff 	struct coeff_ram_ctl *ctl =
290ba6c2959SSteven Eckhoff 		(struct coeff_ram_ctl *)kcontrol->private_value;
291ba6c2959SSteven Eckhoff 	struct soc_bytes_ext *params = &ctl->bytes_ext;
292ba6c2959SSteven Eckhoff 	unsigned int coeff_cnt = params->max / COEFF_SIZE;
293ba6c2959SSteven Eckhoff 	int ret;
294ba6c2959SSteven Eckhoff 
295ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->coeff_ram_lock);
296ba6c2959SSteven Eckhoff 
297ba6c2959SSteven Eckhoff 	tscs42xx->coeff_ram_synced = false;
298ba6c2959SSteven Eckhoff 
299ba6c2959SSteven Eckhoff 	memcpy(&tscs42xx->coeff_ram[ctl->addr * COEFF_SIZE],
300ba6c2959SSteven Eckhoff 		ucontrol->value.bytes.data, params->max);
301ba6c2959SSteven Eckhoff 
302ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->pll_lock);
303ba6c2959SSteven Eckhoff 
3044e46c228SKuninori Morimoto 	if (plls_locked(component)) {
3054e46c228SKuninori Morimoto 		ret = write_coeff_ram(component, tscs42xx->coeff_ram,
306ba6c2959SSteven Eckhoff 			ctl->addr, coeff_cnt);
307ba6c2959SSteven Eckhoff 		if (ret < 0) {
3084e46c228SKuninori Morimoto 			dev_err(component->dev,
309ba6c2959SSteven Eckhoff 				"Failed to flush coeff ram cache (%d)\n", ret);
310ba6c2959SSteven Eckhoff 			goto exit;
311ba6c2959SSteven Eckhoff 		}
312ba6c2959SSteven Eckhoff 		tscs42xx->coeff_ram_synced = true;
313ba6c2959SSteven Eckhoff 	}
314ba6c2959SSteven Eckhoff 
315ba6c2959SSteven Eckhoff 	ret = 0;
316ba6c2959SSteven Eckhoff exit:
317ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->pll_lock);
318ba6c2959SSteven Eckhoff 
319ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->coeff_ram_lock);
320ba6c2959SSteven Eckhoff 
321ba6c2959SSteven Eckhoff 	return ret;
322ba6c2959SSteven Eckhoff }
323ba6c2959SSteven Eckhoff 
324ba6c2959SSteven Eckhoff /* Input L Capture Route */
325ba6c2959SSteven Eckhoff static char const * const input_select_text[] = {
326ba6c2959SSteven Eckhoff 	"Line 1", "Line 2", "Line 3", "D2S"
327ba6c2959SSteven Eckhoff };
328ba6c2959SSteven Eckhoff 
329ba6c2959SSteven Eckhoff static const struct soc_enum left_input_select_enum =
330ba6c2959SSteven Eckhoff SOC_ENUM_SINGLE(R_INSELL, FB_INSELL, ARRAY_SIZE(input_select_text),
331ba6c2959SSteven Eckhoff 		input_select_text);
332ba6c2959SSteven Eckhoff 
333ba6c2959SSteven Eckhoff static const struct snd_kcontrol_new left_input_select =
334ba6c2959SSteven Eckhoff SOC_DAPM_ENUM("LEFT_INPUT_SELECT_ENUM", left_input_select_enum);
335ba6c2959SSteven Eckhoff 
336ba6c2959SSteven Eckhoff /* Input R Capture Route */
337ba6c2959SSteven Eckhoff static const struct soc_enum right_input_select_enum =
338ba6c2959SSteven Eckhoff SOC_ENUM_SINGLE(R_INSELR, FB_INSELR, ARRAY_SIZE(input_select_text),
339ba6c2959SSteven Eckhoff 		input_select_text);
340ba6c2959SSteven Eckhoff 
341ba6c2959SSteven Eckhoff static const struct snd_kcontrol_new right_input_select =
342ba6c2959SSteven Eckhoff SOC_DAPM_ENUM("RIGHT_INPUT_SELECT_ENUM", right_input_select_enum);
343ba6c2959SSteven Eckhoff 
344ba6c2959SSteven Eckhoff /* Input Channel Mapping */
345ba6c2959SSteven Eckhoff static char const * const ch_map_select_text[] = {
346ba6c2959SSteven Eckhoff 	"Normal", "Left to Right", "Right to Left", "Swap"
347ba6c2959SSteven Eckhoff };
348ba6c2959SSteven Eckhoff 
349ba6c2959SSteven Eckhoff static const struct soc_enum ch_map_select_enum =
350ba6c2959SSteven Eckhoff SOC_ENUM_SINGLE(R_AIC2, FB_AIC2_ADCDSEL, ARRAY_SIZE(ch_map_select_text),
351ba6c2959SSteven Eckhoff 		ch_map_select_text);
352ba6c2959SSteven Eckhoff 
dapm_vref_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)353ba6c2959SSteven Eckhoff static int dapm_vref_event(struct snd_soc_dapm_widget *w,
354ba6c2959SSteven Eckhoff 			 struct snd_kcontrol *kcontrol, int event)
355ba6c2959SSteven Eckhoff {
356ba6c2959SSteven Eckhoff 	msleep(20);
357ba6c2959SSteven Eckhoff 	return 0;
358ba6c2959SSteven Eckhoff }
359ba6c2959SSteven Eckhoff 
dapm_micb_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)360ba6c2959SSteven Eckhoff static int dapm_micb_event(struct snd_soc_dapm_widget *w,
361ba6c2959SSteven Eckhoff 			 struct snd_kcontrol *kcontrol, int event)
362ba6c2959SSteven Eckhoff {
363ba6c2959SSteven Eckhoff 	msleep(20);
364ba6c2959SSteven Eckhoff 	return 0;
365ba6c2959SSteven Eckhoff }
366ba6c2959SSteven Eckhoff 
pll_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)3673511108aSColin Ian King static int pll_event(struct snd_soc_dapm_widget *w,
368ba6c2959SSteven Eckhoff 		     struct snd_kcontrol *kcontrol, int event)
369ba6c2959SSteven Eckhoff {
3704c4825aeSSteven Eckhoff 	struct snd_soc_component *component =
3714c4825aeSSteven Eckhoff 		snd_soc_dapm_to_component(w->dapm);
372ba6c2959SSteven Eckhoff 	int ret;
373ba6c2959SSteven Eckhoff 
374ba6c2959SSteven Eckhoff 	if (SND_SOC_DAPM_EVENT_ON(event))
3754e46c228SKuninori Morimoto 		ret = power_up_audio_plls(component);
376ba6c2959SSteven Eckhoff 	else
3774e46c228SKuninori Morimoto 		ret = power_down_audio_plls(component);
378ba6c2959SSteven Eckhoff 
379ba6c2959SSteven Eckhoff 	return ret;
380ba6c2959SSteven Eckhoff }
381ba6c2959SSteven Eckhoff 
dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)3823511108aSColin Ian King static int dac_event(struct snd_soc_dapm_widget *w,
383ba6c2959SSteven Eckhoff 		     struct snd_kcontrol *kcontrol, int event)
384ba6c2959SSteven Eckhoff {
3854c4825aeSSteven Eckhoff 	struct snd_soc_component *component =
3864c4825aeSSteven Eckhoff 		snd_soc_dapm_to_component(w->dapm);
3874e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
388ba6c2959SSteven Eckhoff 	int ret;
389ba6c2959SSteven Eckhoff 
390ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->coeff_ram_lock);
391ba6c2959SSteven Eckhoff 
392f361ca36SPierre-Louis Bossart 	if (!tscs42xx->coeff_ram_synced) {
3934e46c228SKuninori Morimoto 		ret = write_coeff_ram(component, tscs42xx->coeff_ram, 0x00,
394ba6c2959SSteven Eckhoff 			COEFF_RAM_COEFF_COUNT);
395ba6c2959SSteven Eckhoff 		if (ret < 0)
396ba6c2959SSteven Eckhoff 			goto exit;
397ba6c2959SSteven Eckhoff 		tscs42xx->coeff_ram_synced = true;
398ba6c2959SSteven Eckhoff 	}
399ba6c2959SSteven Eckhoff 
400ba6c2959SSteven Eckhoff 	ret = 0;
401ba6c2959SSteven Eckhoff exit:
402ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->coeff_ram_lock);
403ba6c2959SSteven Eckhoff 
404ba6c2959SSteven Eckhoff 	return ret;
405ba6c2959SSteven Eckhoff }
406ba6c2959SSteven Eckhoff 
407ba6c2959SSteven Eckhoff static const struct snd_soc_dapm_widget tscs42xx_dapm_widgets[] = {
408ba6c2959SSteven Eckhoff 	/* Vref */
409ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_SUPPLY_S("Vref", 1, R_PWRM2, FB_PWRM2_VREF, 0,
410ba6c2959SSteven Eckhoff 		dapm_vref_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
411ba6c2959SSteven Eckhoff 
412ba6c2959SSteven Eckhoff 	/* PLL */
413ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, pll_event,
414ba6c2959SSteven Eckhoff 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
415ba6c2959SSteven Eckhoff 
416ba6c2959SSteven Eckhoff 	/* Headphone */
417ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_DAC_E("DAC L", "HiFi Playback", R_PWRM2, FB_PWRM2_HPL, 0,
418ba6c2959SSteven Eckhoff 			dac_event, SND_SOC_DAPM_POST_PMU),
419ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_DAC_E("DAC R", "HiFi Playback", R_PWRM2, FB_PWRM2_HPR, 0,
420ba6c2959SSteven Eckhoff 			dac_event, SND_SOC_DAPM_POST_PMU),
421ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_OUTPUT("Headphone L"),
422ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_OUTPUT("Headphone R"),
423ba6c2959SSteven Eckhoff 
424ba6c2959SSteven Eckhoff 	/* Speaker */
425ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_DAC_E("ClassD L", "HiFi Playback",
426ba6c2959SSteven Eckhoff 		R_PWRM2, FB_PWRM2_SPKL, 0,
427ba6c2959SSteven Eckhoff 		dac_event, SND_SOC_DAPM_POST_PMU),
428ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_DAC_E("ClassD R", "HiFi Playback",
429ba6c2959SSteven Eckhoff 		R_PWRM2, FB_PWRM2_SPKR, 0,
430ba6c2959SSteven Eckhoff 		dac_event, SND_SOC_DAPM_POST_PMU),
431ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_OUTPUT("Speaker L"),
432ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_OUTPUT("Speaker R"),
433ba6c2959SSteven Eckhoff 
434ba6c2959SSteven Eckhoff 	/* Capture */
435ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_PGA("Analog In PGA L", R_PWRM1, FB_PWRM1_PGAL, 0, NULL, 0),
436ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_PGA("Analog In PGA R", R_PWRM1, FB_PWRM1_PGAR, 0, NULL, 0),
437ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_PGA("Analog Boost L", R_PWRM1, FB_PWRM1_BSTL, 0, NULL, 0),
438ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_PGA("Analog Boost R", R_PWRM1, FB_PWRM1_BSTR, 0, NULL, 0),
439ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_PGA("ADC Mute", R_CNVRTR0, FB_CNVRTR0_HPOR, true, NULL, 0),
440ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_ADC("ADC L", "HiFi Capture", R_PWRM1, FB_PWRM1_ADCL, 0),
441ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_ADC("ADC R", "HiFi Capture", R_PWRM1, FB_PWRM1_ADCR, 0),
442ba6c2959SSteven Eckhoff 
443ba6c2959SSteven Eckhoff 	/* Capture Input */
444ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_MUX("Input L Capture Route", R_PWRM2,
445ba6c2959SSteven Eckhoff 			FB_PWRM2_INSELL, 0, &left_input_select),
446ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_MUX("Input R Capture Route", R_PWRM2,
447ba6c2959SSteven Eckhoff 			FB_PWRM2_INSELR, 0, &right_input_select),
448ba6c2959SSteven Eckhoff 
449ba6c2959SSteven Eckhoff 	/* Digital Mic */
450ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_SUPPLY_S("Digital Mic Enable", 2, R_DMICCTL,
451ba6c2959SSteven Eckhoff 		FB_DMICCTL_DMICEN, 0, NULL,
452ba6c2959SSteven Eckhoff 		SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
453ba6c2959SSteven Eckhoff 
454ba6c2959SSteven Eckhoff 	/* Analog Mic */
455ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_SUPPLY_S("Mic Bias", 2, R_PWRM1, FB_PWRM1_MICB,
456ba6c2959SSteven Eckhoff 		0, dapm_micb_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
457ba6c2959SSteven Eckhoff 
458ba6c2959SSteven Eckhoff 	/* Line In */
459ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 1 L"),
460ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 1 R"),
461ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 2 L"),
462ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 2 R"),
463ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 3 L"),
464ba6c2959SSteven Eckhoff 	SND_SOC_DAPM_INPUT("Line In 3 R"),
465ba6c2959SSteven Eckhoff };
466ba6c2959SSteven Eckhoff 
467ba6c2959SSteven Eckhoff static const struct snd_soc_dapm_route tscs42xx_intercon[] = {
468ba6c2959SSteven Eckhoff 	{"DAC L", NULL, "PLL"},
469ba6c2959SSteven Eckhoff 	{"DAC R", NULL, "PLL"},
470ba6c2959SSteven Eckhoff 	{"DAC L", NULL, "Vref"},
471ba6c2959SSteven Eckhoff 	{"DAC R", NULL, "Vref"},
472ba6c2959SSteven Eckhoff 	{"Headphone L", NULL, "DAC L"},
473ba6c2959SSteven Eckhoff 	{"Headphone R", NULL, "DAC R"},
474ba6c2959SSteven Eckhoff 
475ba6c2959SSteven Eckhoff 	{"ClassD L", NULL, "PLL"},
476ba6c2959SSteven Eckhoff 	{"ClassD R", NULL, "PLL"},
477ba6c2959SSteven Eckhoff 	{"ClassD L", NULL, "Vref"},
478ba6c2959SSteven Eckhoff 	{"ClassD R", NULL, "Vref"},
479ba6c2959SSteven Eckhoff 	{"Speaker L", NULL, "ClassD L"},
480ba6c2959SSteven Eckhoff 	{"Speaker R", NULL, "ClassD R"},
481ba6c2959SSteven Eckhoff 
482ba6c2959SSteven Eckhoff 	{"Input L Capture Route", NULL, "Vref"},
483ba6c2959SSteven Eckhoff 	{"Input R Capture Route", NULL, "Vref"},
484ba6c2959SSteven Eckhoff 
485ba6c2959SSteven Eckhoff 	{"Mic Bias", NULL, "Vref"},
486ba6c2959SSteven Eckhoff 
487ba6c2959SSteven Eckhoff 	{"Input L Capture Route", "Line 1", "Line In 1 L"},
488ba6c2959SSteven Eckhoff 	{"Input R Capture Route", "Line 1", "Line In 1 R"},
489ba6c2959SSteven Eckhoff 	{"Input L Capture Route", "Line 2", "Line In 2 L"},
490ba6c2959SSteven Eckhoff 	{"Input R Capture Route", "Line 2", "Line In 2 R"},
491ba6c2959SSteven Eckhoff 	{"Input L Capture Route", "Line 3", "Line In 3 L"},
492ba6c2959SSteven Eckhoff 	{"Input R Capture Route", "Line 3", "Line In 3 R"},
493ba6c2959SSteven Eckhoff 
494ba6c2959SSteven Eckhoff 	{"Analog In PGA L", NULL, "Input L Capture Route"},
495ba6c2959SSteven Eckhoff 	{"Analog In PGA R", NULL, "Input R Capture Route"},
496ba6c2959SSteven Eckhoff 	{"Analog Boost L", NULL, "Analog In PGA L"},
497ba6c2959SSteven Eckhoff 	{"Analog Boost R", NULL, "Analog In PGA R"},
498ba6c2959SSteven Eckhoff 	{"ADC Mute", NULL, "Analog Boost L"},
499ba6c2959SSteven Eckhoff 	{"ADC Mute", NULL, "Analog Boost R"},
500ba6c2959SSteven Eckhoff 	{"ADC L", NULL, "PLL"},
501ba6c2959SSteven Eckhoff 	{"ADC R", NULL, "PLL"},
502ba6c2959SSteven Eckhoff 	{"ADC L", NULL, "ADC Mute"},
503ba6c2959SSteven Eckhoff 	{"ADC R", NULL, "ADC Mute"},
504ba6c2959SSteven Eckhoff };
505ba6c2959SSteven Eckhoff 
506ba6c2959SSteven Eckhoff /************
507ba6c2959SSteven Eckhoff  * CONTROLS *
508ba6c2959SSteven Eckhoff  ************/
509ba6c2959SSteven Eckhoff 
510ba6c2959SSteven Eckhoff static char const * const eq_band_enable_text[] = {
511ba6c2959SSteven Eckhoff 	"Prescale only",
512ba6c2959SSteven Eckhoff 	"Band1",
513ba6c2959SSteven Eckhoff 	"Band1:2",
514ba6c2959SSteven Eckhoff 	"Band1:3",
515ba6c2959SSteven Eckhoff 	"Band1:4",
516ba6c2959SSteven Eckhoff 	"Band1:5",
517ba6c2959SSteven Eckhoff 	"Band1:6",
518ba6c2959SSteven Eckhoff };
519ba6c2959SSteven Eckhoff 
520ba6c2959SSteven Eckhoff static char const * const level_detection_text[] = {
521ba6c2959SSteven Eckhoff 	"Average",
522ba6c2959SSteven Eckhoff 	"Peak",
523ba6c2959SSteven Eckhoff };
524ba6c2959SSteven Eckhoff 
525ba6c2959SSteven Eckhoff static char const * const level_detection_window_text[] = {
526ba6c2959SSteven Eckhoff 	"512 Samples",
527ba6c2959SSteven Eckhoff 	"64 Samples",
528ba6c2959SSteven Eckhoff };
529ba6c2959SSteven Eckhoff 
530ba6c2959SSteven Eckhoff static char const * const compressor_ratio_text[] = {
531ba6c2959SSteven Eckhoff 	"Reserved", "1.5:1", "2:1", "3:1", "4:1", "5:1", "6:1",
532ba6c2959SSteven Eckhoff 	"7:1", "8:1", "9:1", "10:1", "11:1", "12:1", "13:1", "14:1",
533ba6c2959SSteven Eckhoff 	"15:1", "16:1", "17:1", "18:1", "19:1", "20:1",
534ba6c2959SSteven Eckhoff };
535ba6c2959SSteven Eckhoff 
536ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(hpvol_scale, -8850, 75, 0);
537ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(spkvol_scale, -7725, 75, 0);
538ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(dacvol_scale, -9563, 38, 0);
539ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(adcvol_scale, -7125, 38, 0);
540ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(invol_scale, -1725, 75, 0);
541ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_SCALE(mic_boost_scale, 0, 1000, 0);
542ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_MINMAX(mugain_scale, 0, 4650);
543ba6c2959SSteven Eckhoff static DECLARE_TLV_DB_MINMAX(compth_scale, -9562, 0);
544ba6c2959SSteven Eckhoff 
545ba6c2959SSteven Eckhoff static const struct soc_enum eq1_band_enable_enum =
546ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_CONFIG1, FB_CONFIG1_EQ1_BE,
547ba6c2959SSteven Eckhoff 		ARRAY_SIZE(eq_band_enable_text), eq_band_enable_text);
548ba6c2959SSteven Eckhoff 
549ba6c2959SSteven Eckhoff static const struct soc_enum eq2_band_enable_enum =
550ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_CONFIG1, FB_CONFIG1_EQ2_BE,
551ba6c2959SSteven Eckhoff 		ARRAY_SIZE(eq_band_enable_text), eq_band_enable_text);
552ba6c2959SSteven Eckhoff 
553ba6c2959SSteven Eckhoff static const struct soc_enum cle_level_detection_enum =
554ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_CLECTL, FB_CLECTL_LVL_MODE,
555ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_text),
556ba6c2959SSteven Eckhoff 		level_detection_text);
557ba6c2959SSteven Eckhoff 
558ba6c2959SSteven Eckhoff static const struct soc_enum cle_level_detection_window_enum =
559ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_CLECTL, FB_CLECTL_WINDOWSEL,
560ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_window_text),
561ba6c2959SSteven Eckhoff 		level_detection_window_text);
562ba6c2959SSteven Eckhoff 
563ba6c2959SSteven Eckhoff static const struct soc_enum mbc_level_detection_enums[] = {
564ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE1,
565ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_text),
566ba6c2959SSteven Eckhoff 			level_detection_text),
567ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE2,
568ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_text),
569ba6c2959SSteven Eckhoff 			level_detection_text),
570ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE3,
571ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_text),
572ba6c2959SSteven Eckhoff 			level_detection_text),
573ba6c2959SSteven Eckhoff };
574ba6c2959SSteven Eckhoff 
575ba6c2959SSteven Eckhoff static const struct soc_enum mbc_level_detection_window_enums[] = {
576ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL1,
577ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_window_text),
578ba6c2959SSteven Eckhoff 			level_detection_window_text),
579ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL2,
580ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_window_text),
581ba6c2959SSteven Eckhoff 			level_detection_window_text),
582ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL3,
583ba6c2959SSteven Eckhoff 		ARRAY_SIZE(level_detection_window_text),
584ba6c2959SSteven Eckhoff 			level_detection_window_text),
585ba6c2959SSteven Eckhoff };
586ba6c2959SSteven Eckhoff 
587ba6c2959SSteven Eckhoff static const struct soc_enum compressor_ratio_enum =
588ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_CMPRAT, FB_CMPRAT,
589ba6c2959SSteven Eckhoff 		ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
590ba6c2959SSteven Eckhoff 
591ba6c2959SSteven Eckhoff static const struct soc_enum dac_mbc1_compressor_ratio_enum =
592ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCRAT1, FB_DACMBCRAT1_RATIO,
593ba6c2959SSteven Eckhoff 		ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
594ba6c2959SSteven Eckhoff 
595ba6c2959SSteven Eckhoff static const struct soc_enum dac_mbc2_compressor_ratio_enum =
596ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCRAT2, FB_DACMBCRAT2_RATIO,
597ba6c2959SSteven Eckhoff 		ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
598ba6c2959SSteven Eckhoff 
599ba6c2959SSteven Eckhoff static const struct soc_enum dac_mbc3_compressor_ratio_enum =
600ba6c2959SSteven Eckhoff 	SOC_ENUM_SINGLE(R_DACMBCRAT3, FB_DACMBCRAT3_RATIO,
601ba6c2959SSteven Eckhoff 		ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
602ba6c2959SSteven Eckhoff 
bytes_info_ext(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * ucontrol)603ba6c2959SSteven Eckhoff static int bytes_info_ext(struct snd_kcontrol *kcontrol,
604ba6c2959SSteven Eckhoff 	struct snd_ctl_elem_info *ucontrol)
605ba6c2959SSteven Eckhoff {
606ba6c2959SSteven Eckhoff 	struct coeff_ram_ctl *ctl =
607ba6c2959SSteven Eckhoff 		(struct coeff_ram_ctl *)kcontrol->private_value;
608ba6c2959SSteven Eckhoff 	struct soc_bytes_ext *params = &ctl->bytes_ext;
609ba6c2959SSteven Eckhoff 
610ba6c2959SSteven Eckhoff 	ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
611ba6c2959SSteven Eckhoff 	ucontrol->count = params->max;
612ba6c2959SSteven Eckhoff 
613ba6c2959SSteven Eckhoff 	return 0;
614ba6c2959SSteven Eckhoff }
615ba6c2959SSteven Eckhoff 
616ba6c2959SSteven Eckhoff #define COEFF_RAM_CTL(xname, xcount, xaddr) \
617ba6c2959SSteven Eckhoff {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
618ba6c2959SSteven Eckhoff 	.info = bytes_info_ext, \
619ba6c2959SSteven Eckhoff 	.get = coeff_ram_get, .put = coeff_ram_put, \
620ba6c2959SSteven Eckhoff 	.private_value = (unsigned long)&(struct coeff_ram_ctl) { \
621ba6c2959SSteven Eckhoff 		.addr = xaddr, \
622ba6c2959SSteven Eckhoff 		.bytes_ext = {.max = xcount, }, \
623ba6c2959SSteven Eckhoff 	} \
624ba6c2959SSteven Eckhoff }
625ba6c2959SSteven Eckhoff 
626ba6c2959SSteven Eckhoff static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
627ba6c2959SSteven Eckhoff 	/* Volumes */
62819d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("Headphone Volume", R_HPVOLL, R_HPVOLR,
629ba6c2959SSteven Eckhoff 			FB_HPVOLL, 0x7F, 0, hpvol_scale),
63019d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("Speaker Volume", R_SPKVOLL, R_SPKVOLR,
631ba6c2959SSteven Eckhoff 			FB_SPKVOLL, 0x7F, 0, spkvol_scale),
63219d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("Master Volume", R_DACVOLL, R_DACVOLR,
633ba6c2959SSteven Eckhoff 			FB_DACVOLL, 0xFF, 0, dacvol_scale),
63419d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("PCM Volume", R_ADCVOLL, R_ADCVOLR,
635ba6c2959SSteven Eckhoff 			FB_ADCVOLL, 0xFF, 0, adcvol_scale),
63619d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("Input Volume", R_INVOLL, R_INVOLR,
637ba6c2959SSteven Eckhoff 			FB_INVOLL, 0x3F, 0, invol_scale),
638ba6c2959SSteven Eckhoff 
639ba6c2959SSteven Eckhoff 	/* INSEL */
64019d996ccSSteven Eckhoff 	SOC_DOUBLE_R_TLV("Mic Boost Volume", R_INSELL, R_INSELR,
641ba6c2959SSteven Eckhoff 			FB_INSELL_MICBSTL, FV_INSELL_MICBSTL_30DB,
642ba6c2959SSteven Eckhoff 			0, mic_boost_scale),
643ba6c2959SSteven Eckhoff 
644ba6c2959SSteven Eckhoff 	/* Input Channel Map */
645599522eaSSteven Eckhoff 	SOC_ENUM("Input Channel Map", ch_map_select_enum),
646ba6c2959SSteven Eckhoff 
64758f7d470SSteven Eckhoff 	/* Mic Bias */
64858f7d470SSteven Eckhoff 	SOC_SINGLE("Mic Bias Boost Switch", 0x71, 0x07, 1, 0),
64958f7d470SSteven Eckhoff 
65053af408cSSteven Eckhoff 	/* Headphone Auto Switching */
65153af408cSSteven Eckhoff 	SOC_SINGLE("Headphone Auto Switching Switch",
65253af408cSSteven Eckhoff 			R_CTL, FB_CTL_HPSWEN, 1, 0),
65353af408cSSteven Eckhoff 	SOC_SINGLE("Headphone Detect Polarity Toggle Switch",
65453af408cSSteven Eckhoff 			R_CTL, FB_CTL_HPSWPOL, 1, 0),
65553af408cSSteven Eckhoff 
656ba6c2959SSteven Eckhoff 	/* Coefficient Ram */
657ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad1", BIQUAD_SIZE, 0x00),
658ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad2", BIQUAD_SIZE, 0x05),
659ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad3", BIQUAD_SIZE, 0x0a),
660ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad4", BIQUAD_SIZE, 0x0f),
661ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad5", BIQUAD_SIZE, 0x14),
662ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L BiQuad6", BIQUAD_SIZE, 0x19),
663ba6c2959SSteven Eckhoff 
664ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad1", BIQUAD_SIZE, 0x20),
665ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad2", BIQUAD_SIZE, 0x25),
666ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad3", BIQUAD_SIZE, 0x2a),
667ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad4", BIQUAD_SIZE, 0x2f),
668ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad5", BIQUAD_SIZE, 0x34),
669ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R BiQuad6", BIQUAD_SIZE, 0x39),
670ba6c2959SSteven Eckhoff 
671ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1L Prescale", COEFF_SIZE, 0x1f),
672ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade1R Prescale", COEFF_SIZE, 0x3f),
673ba6c2959SSteven Eckhoff 
674ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad1", BIQUAD_SIZE, 0x40),
675ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad2", BIQUAD_SIZE, 0x45),
676ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad3", BIQUAD_SIZE, 0x4a),
677ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad4", BIQUAD_SIZE, 0x4f),
678ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad5", BIQUAD_SIZE, 0x54),
679ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L BiQuad6", BIQUAD_SIZE, 0x59),
680ba6c2959SSteven Eckhoff 
681ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad1", BIQUAD_SIZE, 0x60),
682ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad2", BIQUAD_SIZE, 0x65),
683ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad3", BIQUAD_SIZE, 0x6a),
684ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad4", BIQUAD_SIZE, 0x6f),
685ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad5", BIQUAD_SIZE, 0x74),
686ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R BiQuad6", BIQUAD_SIZE, 0x79),
687ba6c2959SSteven Eckhoff 
688ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2L Prescale", COEFF_SIZE, 0x5f),
689ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Cascade2R Prescale", COEFF_SIZE, 0x7f),
690ba6c2959SSteven Eckhoff 
691ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Extraction BiQuad1", BIQUAD_SIZE, 0x80),
692ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Extraction BiQuad2", BIQUAD_SIZE, 0x85),
693ba6c2959SSteven Eckhoff 
694ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Non Linear Function 1", COEFF_SIZE, 0x8a),
695ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Non Linear Function 2", COEFF_SIZE, 0x8b),
696ba6c2959SSteven Eckhoff 
697ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Limiter BiQuad", BIQUAD_SIZE, 0x8c),
698ba6c2959SSteven Eckhoff 
699ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Cut Off BiQuad", BIQUAD_SIZE, 0x91),
700ba6c2959SSteven Eckhoff 
701ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Bass Mix", COEFF_SIZE, 0x96),
702ba6c2959SSteven Eckhoff 
703ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Extraction BiQuad1", BIQUAD_SIZE, 0x97),
704ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Extraction BiQuad2", BIQUAD_SIZE, 0x9c),
705ba6c2959SSteven Eckhoff 
706ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Non Linear Function 1", COEFF_SIZE, 0xa1),
707ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Non Linear Function 2", COEFF_SIZE, 0xa2),
708ba6c2959SSteven Eckhoff 
709ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Limiter BiQuad", BIQUAD_SIZE, 0xa3),
710ba6c2959SSteven Eckhoff 
711ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Cut Off BiQuad", BIQUAD_SIZE, 0xa8),
712ba6c2959SSteven Eckhoff 
713ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("Treb Mix", COEFF_SIZE, 0xad),
714ba6c2959SSteven Eckhoff 
715ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("3D", COEFF_SIZE, 0xae),
716ba6c2959SSteven Eckhoff 
717ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("3D Mix", COEFF_SIZE, 0xaf),
718ba6c2959SSteven Eckhoff 
719ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC1 BiQuad1", BIQUAD_SIZE, 0xb0),
720ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC1 BiQuad2", BIQUAD_SIZE, 0xb5),
721ba6c2959SSteven Eckhoff 
722ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC2 BiQuad1", BIQUAD_SIZE, 0xba),
723ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC2 BiQuad2", BIQUAD_SIZE, 0xbf),
724ba6c2959SSteven Eckhoff 
725ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC3 BiQuad1", BIQUAD_SIZE, 0xc4),
726ba6c2959SSteven Eckhoff 	COEFF_RAM_CTL("MBC3 BiQuad2", BIQUAD_SIZE, 0xc9),
727ba6c2959SSteven Eckhoff 
728ba6c2959SSteven Eckhoff 	/* EQ */
729ba6c2959SSteven Eckhoff 	SOC_SINGLE("EQ1 Switch", R_CONFIG1, FB_CONFIG1_EQ1_EN, 1, 0),
730ba6c2959SSteven Eckhoff 	SOC_SINGLE("EQ2 Switch", R_CONFIG1, FB_CONFIG1_EQ2_EN, 1, 0),
731599522eaSSteven Eckhoff 	SOC_ENUM("EQ1 Band Enable", eq1_band_enable_enum),
732599522eaSSteven Eckhoff 	SOC_ENUM("EQ2 Band Enable", eq2_band_enable_enum),
733ba6c2959SSteven Eckhoff 
734ba6c2959SSteven Eckhoff 	/* CLE */
735599522eaSSteven Eckhoff 	SOC_ENUM("CLE Level Detect",
736ba6c2959SSteven Eckhoff 		cle_level_detection_enum),
737599522eaSSteven Eckhoff 	SOC_ENUM("CLE Level Detect Win",
738ba6c2959SSteven Eckhoff 		cle_level_detection_window_enum),
739ba6c2959SSteven Eckhoff 	SOC_SINGLE("Expander Switch",
740ba6c2959SSteven Eckhoff 		R_CLECTL, FB_CLECTL_EXP_EN, 1, 0),
741ba6c2959SSteven Eckhoff 	SOC_SINGLE("Limiter Switch",
742ba6c2959SSteven Eckhoff 		R_CLECTL, FB_CLECTL_LIMIT_EN, 1, 0),
743ba6c2959SSteven Eckhoff 	SOC_SINGLE("Comp Switch",
744ba6c2959SSteven Eckhoff 		R_CLECTL, FB_CLECTL_COMP_EN, 1, 0),
74519d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("CLE Make-Up Gain Volume",
746ba6c2959SSteven Eckhoff 		R_MUGAIN, FB_MUGAIN_CLEMUG, 0x1f, 0, mugain_scale),
74719d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("Comp Thresh Volume",
748ba6c2959SSteven Eckhoff 		R_COMPTH, FB_COMPTH, 0xff, 0, compth_scale),
749599522eaSSteven Eckhoff 	SOC_ENUM("Comp Ratio", compressor_ratio_enum),
750ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("Comp Atk Time", R_CATKTCL, 2),
751ba6c2959SSteven Eckhoff 
752ba6c2959SSteven Eckhoff 	/* Effects */
753ba6c2959SSteven Eckhoff 	SOC_SINGLE("3D Switch", R_FXCTL, FB_FXCTL_3DEN, 1, 0),
754ba6c2959SSteven Eckhoff 	SOC_SINGLE("Treble Switch", R_FXCTL, FB_FXCTL_TEEN, 1, 0),
755ba6c2959SSteven Eckhoff 	SOC_SINGLE("Treble Bypass Switch", R_FXCTL, FB_FXCTL_TNLFBYPASS, 1, 0),
756ba6c2959SSteven Eckhoff 	SOC_SINGLE("Bass Switch", R_FXCTL, FB_FXCTL_BEEN, 1, 0),
757ba6c2959SSteven Eckhoff 	SOC_SINGLE("Bass Bypass Switch", R_FXCTL, FB_FXCTL_BNLFBYPASS, 1, 0),
758ba6c2959SSteven Eckhoff 
759ba6c2959SSteven Eckhoff 	/* MBC */
760ba6c2959SSteven Eckhoff 	SOC_SINGLE("MBC Band1 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN1, 1, 0),
761ba6c2959SSteven Eckhoff 	SOC_SINGLE("MBC Band2 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN2, 1, 0),
762ba6c2959SSteven Eckhoff 	SOC_SINGLE("MBC Band3 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN3, 1, 0),
763599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band1 Level Detect",
764ba6c2959SSteven Eckhoff 		mbc_level_detection_enums[0]),
765599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band2 Level Detect",
766ba6c2959SSteven Eckhoff 		mbc_level_detection_enums[1]),
767599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band3 Level Detect",
768ba6c2959SSteven Eckhoff 		mbc_level_detection_enums[2]),
769599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band1 Level Detect Win",
770ba6c2959SSteven Eckhoff 		mbc_level_detection_window_enums[0]),
771599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band2 Level Detect Win",
772ba6c2959SSteven Eckhoff 		mbc_level_detection_window_enums[1]),
773599522eaSSteven Eckhoff 	SOC_ENUM("MBC Band3 Level Detect Win",
774ba6c2959SSteven Eckhoff 		mbc_level_detection_window_enums[2]),
775ba6c2959SSteven Eckhoff 
776599522eaSSteven Eckhoff 	SOC_SINGLE("MBC1 Phase Invert Switch",
777599522eaSSteven Eckhoff 		R_DACMBCMUG1, FB_DACMBCMUG1_PHASE, 1, 0),
77819d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Volume",
779ba6c2959SSteven Eckhoff 		R_DACMBCMUG1, FB_DACMBCMUG1_MUGAIN, 0x1f, 0, mugain_scale),
78019d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Volume",
781ba6c2959SSteven Eckhoff 		R_DACMBCTHR1, FB_DACMBCTHR1_THRESH, 0xff, 0, compth_scale),
782599522eaSSteven Eckhoff 	SOC_ENUM("DAC MBC1 Comp Ratio",
783ba6c2959SSteven Eckhoff 		dac_mbc1_compressor_ratio_enum),
784ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC1 Comp Atk Time", R_DACMBCATK1L, 2),
785ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC1 Comp Rel Time Const",
786ba6c2959SSteven Eckhoff 		R_DACMBCREL1L, 2),
787ba6c2959SSteven Eckhoff 
788599522eaSSteven Eckhoff 	SOC_SINGLE("MBC2 Phase Invert Switch",
789599522eaSSteven Eckhoff 		R_DACMBCMUG2, FB_DACMBCMUG2_PHASE, 1, 0),
79019d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Volume",
791ba6c2959SSteven Eckhoff 		R_DACMBCMUG2, FB_DACMBCMUG2_MUGAIN, 0x1f, 0, mugain_scale),
79219d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Volume",
793ba6c2959SSteven Eckhoff 		R_DACMBCTHR2, FB_DACMBCTHR2_THRESH, 0xff, 0, compth_scale),
794599522eaSSteven Eckhoff 	SOC_ENUM("DAC MBC2 Comp Ratio",
795ba6c2959SSteven Eckhoff 		dac_mbc2_compressor_ratio_enum),
796ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC2 Comp Atk Time", R_DACMBCATK2L, 2),
797ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC2 Comp Rel Time Const",
798ba6c2959SSteven Eckhoff 		R_DACMBCREL2L, 2),
799ba6c2959SSteven Eckhoff 
800599522eaSSteven Eckhoff 	SOC_SINGLE("MBC3 Phase Invert Switch",
801599522eaSSteven Eckhoff 		R_DACMBCMUG3, FB_DACMBCMUG3_PHASE, 1, 0),
80219d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Volume",
803ba6c2959SSteven Eckhoff 		R_DACMBCMUG3, FB_DACMBCMUG3_MUGAIN, 0x1f, 0, mugain_scale),
80419d996ccSSteven Eckhoff 	SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Volume",
805ba6c2959SSteven Eckhoff 		R_DACMBCTHR3, FB_DACMBCTHR3_THRESH, 0xff, 0, compth_scale),
806599522eaSSteven Eckhoff 	SOC_ENUM("DAC MBC3 Comp Ratio",
807ba6c2959SSteven Eckhoff 		dac_mbc3_compressor_ratio_enum),
808ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC3 Comp Atk Time", R_DACMBCATK3L, 2),
809ba6c2959SSteven Eckhoff 	SND_SOC_BYTES("DAC MBC3 Comp Rel Time Const",
810ba6c2959SSteven Eckhoff 		R_DACMBCREL3L, 2),
811ba6c2959SSteven Eckhoff };
812ba6c2959SSteven Eckhoff 
setup_sample_format(struct snd_soc_component * component,snd_pcm_format_t format)8134e46c228SKuninori Morimoto static int setup_sample_format(struct snd_soc_component *component,
814ba6c2959SSteven Eckhoff 		snd_pcm_format_t format)
815ba6c2959SSteven Eckhoff {
816ba6c2959SSteven Eckhoff 	unsigned int width;
817ba6c2959SSteven Eckhoff 	int ret;
818ba6c2959SSteven Eckhoff 
819ba6c2959SSteven Eckhoff 	switch (format) {
820ba6c2959SSteven Eckhoff 	case SNDRV_PCM_FORMAT_S16_LE:
821ba6c2959SSteven Eckhoff 		width = RV_AIC1_WL_16;
822ba6c2959SSteven Eckhoff 		break;
823ba6c2959SSteven Eckhoff 	case SNDRV_PCM_FORMAT_S20_3LE:
824ba6c2959SSteven Eckhoff 		width = RV_AIC1_WL_20;
825ba6c2959SSteven Eckhoff 		break;
826ba6c2959SSteven Eckhoff 	case SNDRV_PCM_FORMAT_S24_LE:
827ba6c2959SSteven Eckhoff 		width = RV_AIC1_WL_24;
828ba6c2959SSteven Eckhoff 		break;
829ba6c2959SSteven Eckhoff 	case SNDRV_PCM_FORMAT_S32_LE:
830ba6c2959SSteven Eckhoff 		width = RV_AIC1_WL_32;
831ba6c2959SSteven Eckhoff 		break;
832ba6c2959SSteven Eckhoff 	default:
833ba6c2959SSteven Eckhoff 		ret = -EINVAL;
8344e46c228SKuninori Morimoto 		dev_err(component->dev, "Unsupported format width (%d)\n", ret);
835ba6c2959SSteven Eckhoff 		return ret;
836ba6c2959SSteven Eckhoff 	}
8374c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
8384c4825aeSSteven Eckhoff 			R_AIC1, RM_AIC1_WL, width);
839ba6c2959SSteven Eckhoff 	if (ret < 0) {
8404c4825aeSSteven Eckhoff 		dev_err(component->dev,
8414c4825aeSSteven Eckhoff 				"Failed to set sample width (%d)\n", ret);
842ba6c2959SSteven Eckhoff 		return ret;
843ba6c2959SSteven Eckhoff 	}
844ba6c2959SSteven Eckhoff 
845ba6c2959SSteven Eckhoff 	return 0;
846ba6c2959SSteven Eckhoff }
847ba6c2959SSteven Eckhoff 
setup_sample_rate(struct snd_soc_component * component,unsigned int rate)8484c4825aeSSteven Eckhoff static int setup_sample_rate(struct snd_soc_component *component,
8494c4825aeSSteven Eckhoff 		unsigned int rate)
850ba6c2959SSteven Eckhoff {
8514e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
852ba6c2959SSteven Eckhoff 	unsigned int br, bm;
853ba6c2959SSteven Eckhoff 	int ret;
854ba6c2959SSteven Eckhoff 
855ba6c2959SSteven Eckhoff 	switch (rate) {
856ba6c2959SSteven Eckhoff 	case 8000:
857ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_32;
858ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_PT25;
859ba6c2959SSteven Eckhoff 		break;
860ba6c2959SSteven Eckhoff 	case 16000:
861ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_32;
862ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_PT5;
863ba6c2959SSteven Eckhoff 		break;
864ba6c2959SSteven Eckhoff 	case 24000:
865ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_48;
866ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_PT5;
867ba6c2959SSteven Eckhoff 		break;
868ba6c2959SSteven Eckhoff 	case 32000:
869ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_32;
870ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_1;
871ba6c2959SSteven Eckhoff 		break;
872ba6c2959SSteven Eckhoff 	case 48000:
873ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_48;
874ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_1;
875ba6c2959SSteven Eckhoff 		break;
876ba6c2959SSteven Eckhoff 	case 96000:
877ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_48;
878ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_2;
879ba6c2959SSteven Eckhoff 		break;
880ba6c2959SSteven Eckhoff 	case 11025:
881ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_44_1;
882ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_PT25;
883ba6c2959SSteven Eckhoff 		break;
884ba6c2959SSteven Eckhoff 	case 22050:
885ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_44_1;
886ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_PT5;
887ba6c2959SSteven Eckhoff 		break;
888ba6c2959SSteven Eckhoff 	case 44100:
889ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_44_1;
890ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_1;
891ba6c2959SSteven Eckhoff 		break;
892ba6c2959SSteven Eckhoff 	case 88200:
893ba6c2959SSteven Eckhoff 		br = RV_DACSR_DBR_44_1;
894ba6c2959SSteven Eckhoff 		bm = RV_DACSR_DBM_2;
895ba6c2959SSteven Eckhoff 		break;
896ba6c2959SSteven Eckhoff 	default:
8974e46c228SKuninori Morimoto 		dev_err(component->dev, "Unsupported sample rate %d\n", rate);
898ba6c2959SSteven Eckhoff 		return -EINVAL;
899ba6c2959SSteven Eckhoff 	}
900ba6c2959SSteven Eckhoff 
901ba6c2959SSteven Eckhoff 	/* DAC and ADC share bit and frame clock */
9024c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
9034c4825aeSSteven Eckhoff 			R_DACSR, RM_DACSR_DBR, br);
904ba6c2959SSteven Eckhoff 	if (ret < 0) {
9054c4825aeSSteven Eckhoff 		dev_err(component->dev,
9064c4825aeSSteven Eckhoff 				"Failed to update register (%d)\n", ret);
907ba6c2959SSteven Eckhoff 		return ret;
908ba6c2959SSteven Eckhoff 	}
9094c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
9104c4825aeSSteven Eckhoff 			R_DACSR, RM_DACSR_DBM, bm);
911ba6c2959SSteven Eckhoff 	if (ret < 0) {
9124c4825aeSSteven Eckhoff 		dev_err(component->dev,
9134c4825aeSSteven Eckhoff 				"Failed to update register (%d)\n", ret);
914ba6c2959SSteven Eckhoff 		return ret;
915ba6c2959SSteven Eckhoff 	}
9164c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
9174c4825aeSSteven Eckhoff 			R_ADCSR, RM_DACSR_DBR, br);
918ba6c2959SSteven Eckhoff 	if (ret < 0) {
9194c4825aeSSteven Eckhoff 		dev_err(component->dev,
9204c4825aeSSteven Eckhoff 				"Failed to update register (%d)\n", ret);
921ba6c2959SSteven Eckhoff 		return ret;
922ba6c2959SSteven Eckhoff 	}
9234c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
9244c4825aeSSteven Eckhoff 			R_ADCSR, RM_DACSR_DBM, bm);
925ba6c2959SSteven Eckhoff 	if (ret < 0) {
9264c4825aeSSteven Eckhoff 		dev_err(component->dev,
9274c4825aeSSteven Eckhoff 				"Failed to update register (%d)\n", ret);
928ba6c2959SSteven Eckhoff 		return ret;
929ba6c2959SSteven Eckhoff 	}
930ba6c2959SSteven Eckhoff 
931ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->audio_params_lock);
932ba6c2959SSteven Eckhoff 
933ba6c2959SSteven Eckhoff 	tscs42xx->samplerate = rate;
934ba6c2959SSteven Eckhoff 
935ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->audio_params_lock);
936ba6c2959SSteven Eckhoff 
937ba6c2959SSteven Eckhoff 	return 0;
938ba6c2959SSteven Eckhoff }
939ba6c2959SSteven Eckhoff 
940ba6c2959SSteven Eckhoff struct reg_setting {
941ba6c2959SSteven Eckhoff 	unsigned int addr;
942ba6c2959SSteven Eckhoff 	unsigned int val;
943ba6c2959SSteven Eckhoff 	unsigned int mask;
944ba6c2959SSteven Eckhoff };
945ba6c2959SSteven Eckhoff 
946ba6c2959SSteven Eckhoff #define PLL_REG_SETTINGS_COUNT 13
947ba6c2959SSteven Eckhoff struct pll_ctl {
948ba6c2959SSteven Eckhoff 	int input_freq;
949ba6c2959SSteven Eckhoff 	struct reg_setting settings[PLL_REG_SETTINGS_COUNT];
950ba6c2959SSteven Eckhoff };
951ba6c2959SSteven Eckhoff 
952ba6c2959SSteven Eckhoff #define PLL_CTL(f, rt, rd, r1b_l, r9, ra, rb,		\
953ba6c2959SSteven Eckhoff 		rc, r12, r1b_h, re, rf, r10, r11)	\
954ba6c2959SSteven Eckhoff 	{						\
955ba6c2959SSteven Eckhoff 		.input_freq = f,			\
956ba6c2959SSteven Eckhoff 		.settings = {				\
957ba6c2959SSteven Eckhoff 			{R_TIMEBASE,  rt,   0xFF},	\
958ba6c2959SSteven Eckhoff 			{R_PLLCTLD,   rd,   0xFF},	\
959ba6c2959SSteven Eckhoff 			{R_PLLCTL1B, r1b_l, 0x0F},	\
960ba6c2959SSteven Eckhoff 			{R_PLLCTL9,   r9,   0xFF},	\
961ba6c2959SSteven Eckhoff 			{R_PLLCTLA,   ra,   0xFF},	\
962ba6c2959SSteven Eckhoff 			{R_PLLCTLB,   rb,   0xFF},	\
963ba6c2959SSteven Eckhoff 			{R_PLLCTLC,   rc,   0xFF},	\
964ba6c2959SSteven Eckhoff 			{R_PLLCTL12, r12,   0xFF},	\
965ba6c2959SSteven Eckhoff 			{R_PLLCTL1B, r1b_h, 0xF0},	\
966ba6c2959SSteven Eckhoff 			{R_PLLCTLE,   re,   0xFF},	\
967ba6c2959SSteven Eckhoff 			{R_PLLCTLF,   rf,   0xFF},	\
968ba6c2959SSteven Eckhoff 			{R_PLLCTL10, r10,   0xFF},	\
969ba6c2959SSteven Eckhoff 			{R_PLLCTL11, r11,   0xFF},	\
970ba6c2959SSteven Eckhoff 		},					\
971ba6c2959SSteven Eckhoff 	}
972ba6c2959SSteven Eckhoff 
973ba6c2959SSteven Eckhoff static const struct pll_ctl pll_ctls[] = {
974ba6c2959SSteven Eckhoff 	PLL_CTL(1411200, 0x05,
975ba6c2959SSteven Eckhoff 		0x39, 0x04, 0x07, 0x02, 0xC3, 0x04,
976ba6c2959SSteven Eckhoff 		0x1B, 0x10, 0x03, 0x03, 0xD0, 0x02),
977ba6c2959SSteven Eckhoff 	PLL_CTL(1536000, 0x05,
978ba6c2959SSteven Eckhoff 		0x1A, 0x04, 0x02, 0x03, 0xE0, 0x01,
979ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x02, 0x03, 0xB9, 0x01),
980ba6c2959SSteven Eckhoff 	PLL_CTL(2822400, 0x0A,
981ba6c2959SSteven Eckhoff 		0x23, 0x04, 0x07, 0x04, 0xC3, 0x04,
982ba6c2959SSteven Eckhoff 		0x22, 0x10, 0x05, 0x03, 0x58, 0x02),
983ba6c2959SSteven Eckhoff 	PLL_CTL(3072000, 0x0B,
984ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x07, 0x03, 0x48, 0x03,
985ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x04, 0x03, 0xB9, 0x01),
986ba6c2959SSteven Eckhoff 	PLL_CTL(5644800, 0x15,
987ba6c2959SSteven Eckhoff 		0x23, 0x04, 0x0E, 0x04, 0xC3, 0x04,
988ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x08, 0x03, 0xE0, 0x01),
989ba6c2959SSteven Eckhoff 	PLL_CTL(6144000, 0x17,
990ba6c2959SSteven Eckhoff 		0x1A, 0x04, 0x08, 0x03, 0xE0, 0x01,
991ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x08, 0x03, 0xB9, 0x01),
992ba6c2959SSteven Eckhoff 	PLL_CTL(12000000, 0x2E,
993ba6c2959SSteven Eckhoff 		0x1B, 0x04, 0x19, 0x03, 0x00, 0x03,
994ba6c2959SSteven Eckhoff 		0x2A, 0x10, 0x19, 0x05, 0x98, 0x04),
995ba6c2959SSteven Eckhoff 	PLL_CTL(19200000, 0x4A,
996ba6c2959SSteven Eckhoff 		0x13, 0x04, 0x14, 0x03, 0x80, 0x01,
997ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x19, 0x03, 0xB9, 0x01),
998ba6c2959SSteven Eckhoff 	PLL_CTL(22000000, 0x55,
999ba6c2959SSteven Eckhoff 		0x2A, 0x04, 0x37, 0x05, 0x00, 0x06,
1000ba6c2959SSteven Eckhoff 		0x22, 0x10, 0x26, 0x03, 0x49, 0x02),
1001ba6c2959SSteven Eckhoff 	PLL_CTL(22579200, 0x57,
1002ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x31, 0x03, 0x20, 0x03,
1003ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x1D, 0x03, 0xB3, 0x01),
1004ba6c2959SSteven Eckhoff 	PLL_CTL(24000000, 0x5D,
1005ba6c2959SSteven Eckhoff 		0x13, 0x04, 0x19, 0x03, 0x80, 0x01,
1006ba6c2959SSteven Eckhoff 		0x1B, 0x10, 0x19, 0x05, 0x4C, 0x02),
1007ba6c2959SSteven Eckhoff 	PLL_CTL(24576000, 0x5F,
1008ba6c2959SSteven Eckhoff 		0x13, 0x04, 0x1D, 0x03, 0xB3, 0x01,
1009ba6c2959SSteven Eckhoff 		0x22, 0x10, 0x40, 0x03, 0x72, 0x03),
1010ba6c2959SSteven Eckhoff 	PLL_CTL(27000000, 0x68,
1011ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x4B, 0x03, 0x00, 0x04,
1012ba6c2959SSteven Eckhoff 		0x2A, 0x10, 0x7D, 0x03, 0x20, 0x06),
1013ba6c2959SSteven Eckhoff 	PLL_CTL(36000000, 0x8C,
1014ba6c2959SSteven Eckhoff 		0x1B, 0x04, 0x4B, 0x03, 0x00, 0x03,
1015ba6c2959SSteven Eckhoff 		0x2A, 0x10, 0x7D, 0x03, 0x98, 0x04),
1016ba6c2959SSteven Eckhoff 	PLL_CTL(25000000, 0x61,
1017ba6c2959SSteven Eckhoff 		0x1B, 0x04, 0x37, 0x03, 0x2B, 0x03,
1018ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x2A, 0x03, 0x39, 0x02),
1019ba6c2959SSteven Eckhoff 	PLL_CTL(26000000, 0x65,
1020ba6c2959SSteven Eckhoff 		0x23, 0x04, 0x41, 0x05, 0x00, 0x06,
1021ba6c2959SSteven Eckhoff 		0x1A, 0x10, 0x26, 0x03, 0xEF, 0x01),
1022ba6c2959SSteven Eckhoff 	PLL_CTL(12288000, 0x2F,
1023ba6c2959SSteven Eckhoff 		0x1A, 0x04, 0x12, 0x03, 0x1C, 0x02,
1024ba6c2959SSteven Eckhoff 		0x22, 0x10, 0x20, 0x03, 0x72, 0x03),
1025ba6c2959SSteven Eckhoff 	PLL_CTL(40000000, 0x9B,
1026ba6c2959SSteven Eckhoff 		0x22, 0x08, 0x7D, 0x03, 0x80, 0x04,
1027ba6c2959SSteven Eckhoff 		0x23, 0x10, 0x7D, 0x05, 0xE4, 0x06),
1028ba6c2959SSteven Eckhoff 	PLL_CTL(512000, 0x01,
1029ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x01, 0x03, 0xD0, 0x02,
1030ba6c2959SSteven Eckhoff 		0x1B, 0x10, 0x01, 0x04, 0x72, 0x03),
1031ba6c2959SSteven Eckhoff 	PLL_CTL(705600, 0x02,
1032ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x02, 0x03, 0x15, 0x04,
1033ba6c2959SSteven Eckhoff 		0x22, 0x10, 0x01, 0x04, 0x80, 0x02),
1034ba6c2959SSteven Eckhoff 	PLL_CTL(1024000, 0x03,
1035ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x02, 0x03, 0xD0, 0x02,
1036ba6c2959SSteven Eckhoff 		0x1B, 0x10, 0x02, 0x04, 0x72, 0x03),
1037ba6c2959SSteven Eckhoff 	PLL_CTL(2048000, 0x07,
1038ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x04, 0x03, 0xD0, 0x02,
1039ba6c2959SSteven Eckhoff 		0x1B, 0x10, 0x04, 0x04, 0x72, 0x03),
1040ba6c2959SSteven Eckhoff 	PLL_CTL(2400000, 0x08,
1041ba6c2959SSteven Eckhoff 		0x22, 0x04, 0x05, 0x03, 0x00, 0x03,
1042ba6c2959SSteven Eckhoff 		0x23, 0x10, 0x05, 0x05, 0x98, 0x04),
1043ba6c2959SSteven Eckhoff };
1044ba6c2959SSteven Eckhoff 
get_pll_ctl(int input_freq)1045ba6c2959SSteven Eckhoff static const struct pll_ctl *get_pll_ctl(int input_freq)
1046ba6c2959SSteven Eckhoff {
1047ba6c2959SSteven Eckhoff 	int i;
1048ba6c2959SSteven Eckhoff 	const struct pll_ctl *pll_ctl = NULL;
1049ba6c2959SSteven Eckhoff 
1050ba6c2959SSteven Eckhoff 	for (i = 0; i < ARRAY_SIZE(pll_ctls); ++i)
1051ba6c2959SSteven Eckhoff 		if (input_freq == pll_ctls[i].input_freq) {
1052ba6c2959SSteven Eckhoff 			pll_ctl = &pll_ctls[i];
1053ba6c2959SSteven Eckhoff 			break;
1054ba6c2959SSteven Eckhoff 		}
1055ba6c2959SSteven Eckhoff 
1056ba6c2959SSteven Eckhoff 	return pll_ctl;
1057ba6c2959SSteven Eckhoff }
1058ba6c2959SSteven Eckhoff 
set_pll_ctl_from_input_freq(struct snd_soc_component * component,const int input_freq)10594e46c228SKuninori Morimoto static int set_pll_ctl_from_input_freq(struct snd_soc_component *component,
1060ba6c2959SSteven Eckhoff 		const int input_freq)
1061ba6c2959SSteven Eckhoff {
1062ba6c2959SSteven Eckhoff 	int ret;
1063ba6c2959SSteven Eckhoff 	int i;
1064ba6c2959SSteven Eckhoff 	const struct pll_ctl *pll_ctl;
1065ba6c2959SSteven Eckhoff 
1066ba6c2959SSteven Eckhoff 	pll_ctl = get_pll_ctl(input_freq);
1067ba6c2959SSteven Eckhoff 	if (!pll_ctl) {
1068ba6c2959SSteven Eckhoff 		ret = -EINVAL;
10694e46c228SKuninori Morimoto 		dev_err(component->dev, "No PLL input entry for %d (%d)\n",
1070ba6c2959SSteven Eckhoff 			input_freq, ret);
1071ba6c2959SSteven Eckhoff 		return ret;
1072ba6c2959SSteven Eckhoff 	}
1073ba6c2959SSteven Eckhoff 
1074ba6c2959SSteven Eckhoff 	for (i = 0; i < PLL_REG_SETTINGS_COUNT; ++i) {
10754e46c228SKuninori Morimoto 		ret = snd_soc_component_update_bits(component,
1076ba6c2959SSteven Eckhoff 			pll_ctl->settings[i].addr,
1077ba6c2959SSteven Eckhoff 			pll_ctl->settings[i].mask,
1078ba6c2959SSteven Eckhoff 			pll_ctl->settings[i].val);
1079ba6c2959SSteven Eckhoff 		if (ret < 0) {
10804e46c228SKuninori Morimoto 			dev_err(component->dev, "Failed to set pll ctl (%d)\n",
1081ba6c2959SSteven Eckhoff 				ret);
1082ba6c2959SSteven Eckhoff 			return ret;
1083ba6c2959SSteven Eckhoff 		}
1084ba6c2959SSteven Eckhoff 	}
1085ba6c2959SSteven Eckhoff 
1086ba6c2959SSteven Eckhoff 	return 0;
1087ba6c2959SSteven Eckhoff }
1088ba6c2959SSteven Eckhoff 
tscs42xx_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * codec_dai)1089ba6c2959SSteven Eckhoff static int tscs42xx_hw_params(struct snd_pcm_substream *substream,
1090ba6c2959SSteven Eckhoff 		struct snd_pcm_hw_params *params,
1091ba6c2959SSteven Eckhoff 		struct snd_soc_dai *codec_dai)
1092ba6c2959SSteven Eckhoff {
10934e46c228SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
1094ba6c2959SSteven Eckhoff 	int ret;
1095ba6c2959SSteven Eckhoff 
10964e46c228SKuninori Morimoto 	ret = setup_sample_format(component, params_format(params));
1097ba6c2959SSteven Eckhoff 	if (ret < 0) {
10984e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to setup sample format (%d)\n",
1099ba6c2959SSteven Eckhoff 			ret);
1100ba6c2959SSteven Eckhoff 		return ret;
1101ba6c2959SSteven Eckhoff 	}
1102ba6c2959SSteven Eckhoff 
11034e46c228SKuninori Morimoto 	ret = setup_sample_rate(component, params_rate(params));
1104ba6c2959SSteven Eckhoff 	if (ret < 0) {
11054c4825aeSSteven Eckhoff 		dev_err(component->dev,
11064c4825aeSSteven Eckhoff 				"Failed to setup sample rate (%d)\n", ret);
1107ba6c2959SSteven Eckhoff 		return ret;
1108ba6c2959SSteven Eckhoff 	}
1109ba6c2959SSteven Eckhoff 
1110ba6c2959SSteven Eckhoff 	return 0;
1111ba6c2959SSteven Eckhoff }
1112ba6c2959SSteven Eckhoff 
dac_mute(struct snd_soc_component * component)11134e46c228SKuninori Morimoto static inline int dac_mute(struct snd_soc_component *component)
1114ba6c2959SSteven Eckhoff {
1115ba6c2959SSteven Eckhoff 	int ret;
1116ba6c2959SSteven Eckhoff 
11174c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
11184c4825aeSSteven Eckhoff 			R_CNVRTR1, RM_CNVRTR1_DACMU,
1119ba6c2959SSteven Eckhoff 		RV_CNVRTR1_DACMU_ENABLE);
1120ba6c2959SSteven Eckhoff 	if (ret < 0) {
11214e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to mute DAC (%d)\n",
1122ba6c2959SSteven Eckhoff 				ret);
1123ba6c2959SSteven Eckhoff 		return ret;
1124ba6c2959SSteven Eckhoff 	}
1125ba6c2959SSteven Eckhoff 
1126ba6c2959SSteven Eckhoff 	return 0;
1127ba6c2959SSteven Eckhoff }
1128ba6c2959SSteven Eckhoff 
dac_unmute(struct snd_soc_component * component)11294e46c228SKuninori Morimoto static inline int dac_unmute(struct snd_soc_component *component)
1130ba6c2959SSteven Eckhoff {
1131ba6c2959SSteven Eckhoff 	int ret;
1132ba6c2959SSteven Eckhoff 
11334c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
11344c4825aeSSteven Eckhoff 			R_CNVRTR1, RM_CNVRTR1_DACMU,
1135ba6c2959SSteven Eckhoff 		RV_CNVRTR1_DACMU_DISABLE);
1136ba6c2959SSteven Eckhoff 	if (ret < 0) {
11374e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to unmute DAC (%d)\n",
1138ba6c2959SSteven Eckhoff 				ret);
1139ba6c2959SSteven Eckhoff 		return ret;
1140ba6c2959SSteven Eckhoff 	}
1141ba6c2959SSteven Eckhoff 
1142ba6c2959SSteven Eckhoff 	return 0;
1143ba6c2959SSteven Eckhoff }
1144ba6c2959SSteven Eckhoff 
adc_mute(struct snd_soc_component * component)11454e46c228SKuninori Morimoto static inline int adc_mute(struct snd_soc_component *component)
1146ba6c2959SSteven Eckhoff {
1147ba6c2959SSteven Eckhoff 	int ret;
1148ba6c2959SSteven Eckhoff 
11494c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
11504c4825aeSSteven Eckhoff 			R_CNVRTR0, RM_CNVRTR0_ADCMU, RV_CNVRTR0_ADCMU_ENABLE);
1151ba6c2959SSteven Eckhoff 	if (ret < 0) {
11524e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to mute ADC (%d)\n",
1153ba6c2959SSteven Eckhoff 				ret);
1154ba6c2959SSteven Eckhoff 		return ret;
1155ba6c2959SSteven Eckhoff 	}
1156ba6c2959SSteven Eckhoff 
1157ba6c2959SSteven Eckhoff 	return 0;
1158ba6c2959SSteven Eckhoff }
1159ba6c2959SSteven Eckhoff 
adc_unmute(struct snd_soc_component * component)11604e46c228SKuninori Morimoto static inline int adc_unmute(struct snd_soc_component *component)
1161ba6c2959SSteven Eckhoff {
1162ba6c2959SSteven Eckhoff 	int ret;
1163ba6c2959SSteven Eckhoff 
11644c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
11654c4825aeSSteven Eckhoff 			R_CNVRTR0, RM_CNVRTR0_ADCMU, RV_CNVRTR0_ADCMU_DISABLE);
1166ba6c2959SSteven Eckhoff 	if (ret < 0) {
11674e46c228SKuninori Morimoto 		dev_err(component->dev, "Failed to unmute ADC (%d)\n",
1168ba6c2959SSteven Eckhoff 				ret);
1169ba6c2959SSteven Eckhoff 		return ret;
1170ba6c2959SSteven Eckhoff 	}
1171ba6c2959SSteven Eckhoff 
1172ba6c2959SSteven Eckhoff 	return 0;
1173ba6c2959SSteven Eckhoff }
1174ba6c2959SSteven Eckhoff 
tscs42xx_mute_stream(struct snd_soc_dai * dai,int mute,int stream)1175ba6c2959SSteven Eckhoff static int tscs42xx_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
1176ba6c2959SSteven Eckhoff {
11774e46c228SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
1178ba6c2959SSteven Eckhoff 	int ret;
1179ba6c2959SSteven Eckhoff 
1180ba6c2959SSteven Eckhoff 	if (mute)
1181ba6c2959SSteven Eckhoff 		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
11824e46c228SKuninori Morimoto 			ret = dac_mute(component);
1183ba6c2959SSteven Eckhoff 		else
11844e46c228SKuninori Morimoto 			ret = adc_mute(component);
1185ba6c2959SSteven Eckhoff 	else
1186ba6c2959SSteven Eckhoff 		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
11874e46c228SKuninori Morimoto 			ret = dac_unmute(component);
1188ba6c2959SSteven Eckhoff 		else
11894e46c228SKuninori Morimoto 			ret = adc_unmute(component);
1190ba6c2959SSteven Eckhoff 
1191ba6c2959SSteven Eckhoff 	return ret;
1192ba6c2959SSteven Eckhoff }
1193ba6c2959SSteven Eckhoff 
tscs42xx_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)1194ba6c2959SSteven Eckhoff static int tscs42xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
1195ba6c2959SSteven Eckhoff 		unsigned int fmt)
1196ba6c2959SSteven Eckhoff {
11974e46c228SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
1198ba6c2959SSteven Eckhoff 	int ret;
1199ba6c2959SSteven Eckhoff 
12007cba0b38SMark Brown 	/* Consumer mode not supported since it needs always-on frame clock */
12017cba0b38SMark Brown 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
12027cba0b38SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
12034c4825aeSSteven Eckhoff 		ret = snd_soc_component_update_bits(component,
12044c4825aeSSteven Eckhoff 				R_AIC1, RM_AIC1_MS, RV_AIC1_MS_MASTER);
1205ba6c2959SSteven Eckhoff 		if (ret < 0) {
12064e46c228SKuninori Morimoto 			dev_err(component->dev,
1207ba6c2959SSteven Eckhoff 				"Failed to set codec DAI master (%d)\n", ret);
1208ba6c2959SSteven Eckhoff 			return ret;
1209ba6c2959SSteven Eckhoff 		}
1210ba6c2959SSteven Eckhoff 		break;
1211ba6c2959SSteven Eckhoff 	default:
1212ba6c2959SSteven Eckhoff 		ret = -EINVAL;
12134e46c228SKuninori Morimoto 		dev_err(component->dev, "Unsupported format (%d)\n", ret);
1214ba6c2959SSteven Eckhoff 		return ret;
1215ba6c2959SSteven Eckhoff 	}
1216ba6c2959SSteven Eckhoff 
1217ba6c2959SSteven Eckhoff 	return 0;
1218ba6c2959SSteven Eckhoff }
1219ba6c2959SSteven Eckhoff 
tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai * codec_dai,unsigned int ratio)1220ba6c2959SSteven Eckhoff static int tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai *codec_dai,
1221ba6c2959SSteven Eckhoff 		unsigned int ratio)
1222ba6c2959SSteven Eckhoff {
12234e46c228SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
12244e46c228SKuninori Morimoto 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
1225ba6c2959SSteven Eckhoff 	unsigned int value;
1226ba6c2959SSteven Eckhoff 	int ret = 0;
1227ba6c2959SSteven Eckhoff 
1228ba6c2959SSteven Eckhoff 	switch (ratio) {
1229ba6c2959SSteven Eckhoff 	case 32:
1230ba6c2959SSteven Eckhoff 		value = RV_DACSR_DBCM_32;
1231ba6c2959SSteven Eckhoff 		break;
1232ba6c2959SSteven Eckhoff 	case 40:
1233ba6c2959SSteven Eckhoff 		value = RV_DACSR_DBCM_40;
1234ba6c2959SSteven Eckhoff 		break;
1235ba6c2959SSteven Eckhoff 	case 64:
1236ba6c2959SSteven Eckhoff 		value = RV_DACSR_DBCM_64;
1237ba6c2959SSteven Eckhoff 		break;
1238ba6c2959SSteven Eckhoff 	default:
12394e46c228SKuninori Morimoto 		dev_err(component->dev, "Unsupported bclk ratio (%d)\n", ret);
1240ba6c2959SSteven Eckhoff 		return -EINVAL;
1241ba6c2959SSteven Eckhoff 	}
1242ba6c2959SSteven Eckhoff 
12434c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
12444c4825aeSSteven Eckhoff 			R_DACSR, RM_DACSR_DBCM, value);
1245ba6c2959SSteven Eckhoff 	if (ret < 0) {
12464c4825aeSSteven Eckhoff 		dev_err(component->dev,
12474c4825aeSSteven Eckhoff 				"Failed to set DAC BCLK ratio (%d)\n", ret);
1248ba6c2959SSteven Eckhoff 		return ret;
1249ba6c2959SSteven Eckhoff 	}
12504c4825aeSSteven Eckhoff 	ret = snd_soc_component_update_bits(component,
12514c4825aeSSteven Eckhoff 			R_ADCSR, RM_ADCSR_ABCM, value);
1252ba6c2959SSteven Eckhoff 	if (ret < 0) {
12534c4825aeSSteven Eckhoff 		dev_err(component->dev,
12544c4825aeSSteven Eckhoff 				"Failed to set ADC BCLK ratio (%d)\n", ret);
1255ba6c2959SSteven Eckhoff 		return ret;
1256ba6c2959SSteven Eckhoff 	}
1257ba6c2959SSteven Eckhoff 
1258ba6c2959SSteven Eckhoff 	mutex_lock(&tscs42xx->audio_params_lock);
1259ba6c2959SSteven Eckhoff 
1260ba6c2959SSteven Eckhoff 	tscs42xx->bclk_ratio = ratio;
1261ba6c2959SSteven Eckhoff 
1262ba6c2959SSteven Eckhoff 	mutex_unlock(&tscs42xx->audio_params_lock);
1263ba6c2959SSteven Eckhoff 
1264ba6c2959SSteven Eckhoff 	return 0;
1265ba6c2959SSteven Eckhoff }
1266ba6c2959SSteven Eckhoff 
1267ba6c2959SSteven Eckhoff static const struct snd_soc_dai_ops tscs42xx_dai_ops = {
1268ba6c2959SSteven Eckhoff 	.hw_params	= tscs42xx_hw_params,
1269ba6c2959SSteven Eckhoff 	.mute_stream	= tscs42xx_mute_stream,
1270ba6c2959SSteven Eckhoff 	.set_fmt	= tscs42xx_set_dai_fmt,
1271ba6c2959SSteven Eckhoff 	.set_bclk_ratio = tscs42xx_set_dai_bclk_ratio,
1272ba6c2959SSteven Eckhoff };
1273ba6c2959SSteven Eckhoff 
part_is_valid(struct tscs42xx * tscs42xx)1274ba6c2959SSteven Eckhoff static int part_is_valid(struct tscs42xx *tscs42xx)
1275ba6c2959SSteven Eckhoff {
1276ba6c2959SSteven Eckhoff 	int val;
1277ba6c2959SSteven Eckhoff 	int ret;
1278ba6c2959SSteven Eckhoff 	unsigned int reg;
1279ba6c2959SSteven Eckhoff 
1280ba6c2959SSteven Eckhoff 	ret = regmap_read(tscs42xx->regmap, R_DEVIDH, &reg);
1281ba6c2959SSteven Eckhoff 	if (ret < 0)
1282ba6c2959SSteven Eckhoff 		return ret;
1283ba6c2959SSteven Eckhoff 
1284ba6c2959SSteven Eckhoff 	val = reg << 8;
1285ba6c2959SSteven Eckhoff 	ret = regmap_read(tscs42xx->regmap, R_DEVIDL, &reg);
1286ba6c2959SSteven Eckhoff 	if (ret < 0)
1287ba6c2959SSteven Eckhoff 		return ret;
1288ba6c2959SSteven Eckhoff 
1289ba6c2959SSteven Eckhoff 	val |= reg;
1290ba6c2959SSteven Eckhoff 
1291ba6c2959SSteven Eckhoff 	switch (val) {
1292ba6c2959SSteven Eckhoff 	case 0x4A74:
1293ba6c2959SSteven Eckhoff 	case 0x4A73:
1294ba6c2959SSteven Eckhoff 		return true;
1295ba6c2959SSteven Eckhoff 	default:
1296ba6c2959SSteven Eckhoff 		return false;
129732c5dca1STom Rix 	}
1298ba6c2959SSteven Eckhoff }
1299ba6c2959SSteven Eckhoff 
set_sysclk(struct snd_soc_component * component)1300aa0f18d7SSteven Eckhoff static int set_sysclk(struct snd_soc_component *component)
1301aa0f18d7SSteven Eckhoff {
1302aa0f18d7SSteven Eckhoff 	struct tscs42xx *tscs42xx = snd_soc_component_get_drvdata(component);
1303aa0f18d7SSteven Eckhoff 	unsigned long freq;
1304aa0f18d7SSteven Eckhoff 	int ret;
1305aa0f18d7SSteven Eckhoff 
1306aa0f18d7SSteven Eckhoff 	switch (tscs42xx->sysclk_src_id) {
1307aa0f18d7SSteven Eckhoff 	case TSCS42XX_PLL_SRC_XTAL:
1308aa0f18d7SSteven Eckhoff 	case TSCS42XX_PLL_SRC_MCLK1:
1309aa0f18d7SSteven Eckhoff 		ret = snd_soc_component_write(component, R_PLLREFSEL,
1310aa0f18d7SSteven Eckhoff 				RV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 |
1311aa0f18d7SSteven Eckhoff 				RV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1);
1312aa0f18d7SSteven Eckhoff 		if (ret < 0) {
1313aa0f18d7SSteven Eckhoff 			dev_err(component->dev,
1314aa0f18d7SSteven Eckhoff 				"Failed to set pll reference input (%d)\n",
1315aa0f18d7SSteven Eckhoff 				ret);
1316aa0f18d7SSteven Eckhoff 			return ret;
1317aa0f18d7SSteven Eckhoff 		}
1318aa0f18d7SSteven Eckhoff 		break;
1319aa0f18d7SSteven Eckhoff 	case TSCS42XX_PLL_SRC_MCLK2:
1320aa0f18d7SSteven Eckhoff 		ret = snd_soc_component_write(component, R_PLLREFSEL,
1321aa0f18d7SSteven Eckhoff 				RV_PLLREFSEL_PLL1_REF_SEL_MCLK2 |
1322aa0f18d7SSteven Eckhoff 				RV_PLLREFSEL_PLL2_REF_SEL_MCLK2);
1323aa0f18d7SSteven Eckhoff 		if (ret < 0) {
1324aa0f18d7SSteven Eckhoff 			dev_err(component->dev,
1325aa0f18d7SSteven Eckhoff 				"Failed to set PLL reference (%d)\n", ret);
1326aa0f18d7SSteven Eckhoff 			return ret;
1327aa0f18d7SSteven Eckhoff 		}
1328aa0f18d7SSteven Eckhoff 		break;
1329aa0f18d7SSteven Eckhoff 	default:
1330aa0f18d7SSteven Eckhoff 		dev_err(component->dev, "pll src is unsupported\n");
1331aa0f18d7SSteven Eckhoff 		return -EINVAL;
1332aa0f18d7SSteven Eckhoff 	}
1333aa0f18d7SSteven Eckhoff 
1334aa0f18d7SSteven Eckhoff 	freq = clk_get_rate(tscs42xx->sysclk);
1335aa0f18d7SSteven Eckhoff 	ret = set_pll_ctl_from_input_freq(component, freq);
1336aa0f18d7SSteven Eckhoff 	if (ret < 0) {
1337aa0f18d7SSteven Eckhoff 		dev_err(component->dev,
1338aa0f18d7SSteven Eckhoff 			"Failed to setup PLL input freq (%d)\n", ret);
1339aa0f18d7SSteven Eckhoff 		return ret;
1340aa0f18d7SSteven Eckhoff 	}
1341aa0f18d7SSteven Eckhoff 
1342aa0f18d7SSteven Eckhoff 	return 0;
1343aa0f18d7SSteven Eckhoff }
1344aa0f18d7SSteven Eckhoff 
tscs42xx_probe(struct snd_soc_component * component)1345aa0f18d7SSteven Eckhoff static int tscs42xx_probe(struct snd_soc_component *component)
1346aa0f18d7SSteven Eckhoff {
1347aa0f18d7SSteven Eckhoff 	return set_sysclk(component);
1348aa0f18d7SSteven Eckhoff }
1349aa0f18d7SSteven Eckhoff 
13504c4825aeSSteven Eckhoff static const struct snd_soc_component_driver soc_codec_dev_tscs42xx = {
1351aa0f18d7SSteven Eckhoff 	.probe			= tscs42xx_probe,
1352ba6c2959SSteven Eckhoff 	.dapm_widgets		= tscs42xx_dapm_widgets,
1353ba6c2959SSteven Eckhoff 	.num_dapm_widgets	= ARRAY_SIZE(tscs42xx_dapm_widgets),
1354ba6c2959SSteven Eckhoff 	.dapm_routes		= tscs42xx_intercon,
1355ba6c2959SSteven Eckhoff 	.num_dapm_routes	= ARRAY_SIZE(tscs42xx_intercon),
1356ba6c2959SSteven Eckhoff 	.controls		= tscs42xx_snd_controls,
1357ba6c2959SSteven Eckhoff 	.num_controls		= ARRAY_SIZE(tscs42xx_snd_controls),
13584e46c228SKuninori Morimoto 	.idle_bias_on		= 1,
13594e46c228SKuninori Morimoto 	.use_pmdown_time	= 1,
13604e46c228SKuninori Morimoto 	.endianness		= 1,
1361ba6c2959SSteven Eckhoff };
1362ba6c2959SSteven Eckhoff 
init_coeff_ram_cache(struct tscs42xx * tscs42xx)1363ba6c2959SSteven Eckhoff static inline void init_coeff_ram_cache(struct tscs42xx *tscs42xx)
1364ba6c2959SSteven Eckhoff {
1365390f7bbdSColin Ian King 	static const u8 norm_addrs[] = {
1366390f7bbdSColin Ian King 		0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1f, 0x20, 0x25, 0x2a,
1367390f7bbdSColin Ian King 		0x2f, 0x34, 0x39, 0x3f, 0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59,
1368390f7bbdSColin Ian King 		0x5f, 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7f, 0x80, 0x85,
1369390f7bbdSColin Ian King 		0x8c, 0x91, 0x96, 0x97, 0x9c, 0xa3, 0xa8, 0xad, 0xaf, 0xb0,
1370390f7bbdSColin Ian King 		0xb5, 0xba, 0xbf, 0xc4, 0xc9,
1371390f7bbdSColin Ian King 	};
1372ba6c2959SSteven Eckhoff 	u8 *coeff_ram = tscs42xx->coeff_ram;
1373ba6c2959SSteven Eckhoff 	int i;
1374ba6c2959SSteven Eckhoff 
1375ba6c2959SSteven Eckhoff 	for (i = 0; i < ARRAY_SIZE(norm_addrs); i++)
1376ba6c2959SSteven Eckhoff 		coeff_ram[((norm_addrs[i] + 1) * COEFF_SIZE) - 1] = 0x40;
1377ba6c2959SSteven Eckhoff }
1378ba6c2959SSteven Eckhoff 
1379ba6c2959SSteven Eckhoff #define TSCS42XX_RATES SNDRV_PCM_RATE_8000_96000
1380ba6c2959SSteven Eckhoff 
1381ba6c2959SSteven Eckhoff #define TSCS42XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
1382ba6c2959SSteven Eckhoff 	| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1383ba6c2959SSteven Eckhoff 
1384ba6c2959SSteven Eckhoff static struct snd_soc_dai_driver tscs42xx_dai = {
1385ba6c2959SSteven Eckhoff 	.name = "tscs42xx-HiFi",
1386ba6c2959SSteven Eckhoff 	.playback = {
1387ba6c2959SSteven Eckhoff 		.stream_name = "HiFi Playback",
1388ba6c2959SSteven Eckhoff 		.channels_min = 2,
1389ba6c2959SSteven Eckhoff 		.channels_max = 2,
1390ba6c2959SSteven Eckhoff 		.rates = TSCS42XX_RATES,
1391ba6c2959SSteven Eckhoff 		.formats = TSCS42XX_FORMATS,},
1392ba6c2959SSteven Eckhoff 	.capture = {
1393ba6c2959SSteven Eckhoff 		.stream_name = "HiFi Capture",
1394ba6c2959SSteven Eckhoff 		.channels_min = 2,
1395ba6c2959SSteven Eckhoff 		.channels_max = 2,
1396ba6c2959SSteven Eckhoff 		.rates = TSCS42XX_RATES,
1397ba6c2959SSteven Eckhoff 		.formats = TSCS42XX_FORMATS,},
1398ba6c2959SSteven Eckhoff 	.ops = &tscs42xx_dai_ops,
13999b4488efSKuninori Morimoto 	.symmetric_rate = 1,
1400ba6c2959SSteven Eckhoff 	.symmetric_channels = 1,
14019b4488efSKuninori Morimoto 	.symmetric_sample_bits = 1,
1402ba6c2959SSteven Eckhoff };
1403ba6c2959SSteven Eckhoff 
1404ba6c2959SSteven Eckhoff static const struct reg_sequence tscs42xx_patch[] = {
1405ba6c2959SSteven Eckhoff 	{ R_AIC2, RV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED },
1406ba6c2959SSteven Eckhoff };
1407ba6c2959SSteven Eckhoff 
1408aa0f18d7SSteven Eckhoff static char const * const src_names[TSCS42XX_PLL_SRC_CNT] = {
1409aa0f18d7SSteven Eckhoff 	"xtal", "mclk1", "mclk2"};
1410aa0f18d7SSteven Eckhoff 
tscs42xx_i2c_probe(struct i2c_client * i2c)1411f950ef91SStephen Kitt static int tscs42xx_i2c_probe(struct i2c_client *i2c)
1412ba6c2959SSteven Eckhoff {
1413ba6c2959SSteven Eckhoff 	struct tscs42xx *tscs42xx;
1414aa0f18d7SSteven Eckhoff 	int src;
1415aa0f18d7SSteven Eckhoff 	int ret;
1416ba6c2959SSteven Eckhoff 
1417ba6c2959SSteven Eckhoff 	tscs42xx = devm_kzalloc(&i2c->dev, sizeof(*tscs42xx), GFP_KERNEL);
1418ba6c2959SSteven Eckhoff 	if (!tscs42xx) {
1419ba6c2959SSteven Eckhoff 		ret = -ENOMEM;
1420ba6c2959SSteven Eckhoff 		dev_err(&i2c->dev,
1421ba6c2959SSteven Eckhoff 			"Failed to allocate memory for data (%d)\n", ret);
1422ba6c2959SSteven Eckhoff 		return ret;
1423ba6c2959SSteven Eckhoff 	}
1424ba6c2959SSteven Eckhoff 	i2c_set_clientdata(i2c, tscs42xx);
1425ba6c2959SSteven Eckhoff 
1426aa0f18d7SSteven Eckhoff 	for (src = TSCS42XX_PLL_SRC_XTAL; src < TSCS42XX_PLL_SRC_CNT; src++) {
1427aa0f18d7SSteven Eckhoff 		tscs42xx->sysclk = devm_clk_get(&i2c->dev, src_names[src]);
1428aa0f18d7SSteven Eckhoff 		if (!IS_ERR(tscs42xx->sysclk)) {
1429aa0f18d7SSteven Eckhoff 			break;
1430aa0f18d7SSteven Eckhoff 		} else if (PTR_ERR(tscs42xx->sysclk) != -ENOENT) {
1431aa0f18d7SSteven Eckhoff 			ret = PTR_ERR(tscs42xx->sysclk);
1432aa0f18d7SSteven Eckhoff 			dev_err(&i2c->dev, "Failed to get sysclk (%d)\n", ret);
1433aa0f18d7SSteven Eckhoff 			return ret;
1434aa0f18d7SSteven Eckhoff 		}
1435aa0f18d7SSteven Eckhoff 	}
1436aa0f18d7SSteven Eckhoff 	if (src == TSCS42XX_PLL_SRC_CNT) {
1437aa0f18d7SSteven Eckhoff 		ret = -EINVAL;
1438aa0f18d7SSteven Eckhoff 		dev_err(&i2c->dev, "Failed to get a valid clock name (%d)\n",
1439aa0f18d7SSteven Eckhoff 				ret);
1440aa0f18d7SSteven Eckhoff 		return ret;
1441aa0f18d7SSteven Eckhoff 	}
1442aa0f18d7SSteven Eckhoff 	tscs42xx->sysclk_src_id = src;
1443aa0f18d7SSteven Eckhoff 
1444ba6c2959SSteven Eckhoff 	tscs42xx->regmap = devm_regmap_init_i2c(i2c, &tscs42xx_regmap);
1445ba6c2959SSteven Eckhoff 	if (IS_ERR(tscs42xx->regmap)) {
1446ba6c2959SSteven Eckhoff 		ret = PTR_ERR(tscs42xx->regmap);
14477ab5ba47SSteven Eckhoff 		dev_err(&i2c->dev, "Failed to allocate regmap (%d)\n", ret);
1448ba6c2959SSteven Eckhoff 		return ret;
1449ba6c2959SSteven Eckhoff 	}
1450ba6c2959SSteven Eckhoff 
1451ba6c2959SSteven Eckhoff 	init_coeff_ram_cache(tscs42xx);
1452ba6c2959SSteven Eckhoff 
1453ba6c2959SSteven Eckhoff 	ret = part_is_valid(tscs42xx);
1454ba6c2959SSteven Eckhoff 	if (ret <= 0) {
14557ab5ba47SSteven Eckhoff 		dev_err(&i2c->dev, "No valid part (%d)\n", ret);
1456ba6c2959SSteven Eckhoff 		ret = -ENODEV;
1457ba6c2959SSteven Eckhoff 		return ret;
1458ba6c2959SSteven Eckhoff 	}
1459ba6c2959SSteven Eckhoff 
1460ba6c2959SSteven Eckhoff 	ret = regmap_write(tscs42xx->regmap, R_RESET, RV_RESET_ENABLE);
1461ba6c2959SSteven Eckhoff 	if (ret < 0) {
14627ab5ba47SSteven Eckhoff 		dev_err(&i2c->dev, "Failed to reset device (%d)\n", ret);
1463ba6c2959SSteven Eckhoff 		return ret;
1464ba6c2959SSteven Eckhoff 	}
1465ba6c2959SSteven Eckhoff 
1466ba6c2959SSteven Eckhoff 	ret = regmap_register_patch(tscs42xx->regmap, tscs42xx_patch,
1467ba6c2959SSteven Eckhoff 			ARRAY_SIZE(tscs42xx_patch));
1468ba6c2959SSteven Eckhoff 	if (ret < 0) {
14697ab5ba47SSteven Eckhoff 		dev_err(&i2c->dev, "Failed to apply patch (%d)\n", ret);
1470ba6c2959SSteven Eckhoff 		return ret;
1471ba6c2959SSteven Eckhoff 	}
1472ba6c2959SSteven Eckhoff 
1473ba6c2959SSteven Eckhoff 	mutex_init(&tscs42xx->audio_params_lock);
1474ba6c2959SSteven Eckhoff 	mutex_init(&tscs42xx->coeff_ram_lock);
1475ba6c2959SSteven Eckhoff 	mutex_init(&tscs42xx->pll_lock);
1476ba6c2959SSteven Eckhoff 
14777ab5ba47SSteven Eckhoff 	ret = devm_snd_soc_register_component(&i2c->dev,
14784c4825aeSSteven Eckhoff 			&soc_codec_dev_tscs42xx, &tscs42xx_dai, 1);
1479ba6c2959SSteven Eckhoff 	if (ret) {
14807ab5ba47SSteven Eckhoff 		dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
1481ba6c2959SSteven Eckhoff 		return ret;
1482ba6c2959SSteven Eckhoff 	}
1483ba6c2959SSteven Eckhoff 
1484ba6c2959SSteven Eckhoff 	return 0;
1485ba6c2959SSteven Eckhoff }
1486ba6c2959SSteven Eckhoff 
1487ba6c2959SSteven Eckhoff static const struct i2c_device_id tscs42xx_i2c_id[] = {
1488ba6c2959SSteven Eckhoff 	{ "tscs42A1", 0 },
1489ba6c2959SSteven Eckhoff 	{ "tscs42A2", 0 },
1490ba6c2959SSteven Eckhoff 	{ }
1491ba6c2959SSteven Eckhoff };
1492ba6c2959SSteven Eckhoff MODULE_DEVICE_TABLE(i2c, tscs42xx_i2c_id);
1493ba6c2959SSteven Eckhoff 
1494ba6c2959SSteven Eckhoff static const struct of_device_id tscs42xx_of_match[] = {
1495ba6c2959SSteven Eckhoff 	{ .compatible = "tempo,tscs42A1", },
1496ba6c2959SSteven Eckhoff 	{ .compatible = "tempo,tscs42A2", },
1497ba6c2959SSteven Eckhoff 	{ }
1498ba6c2959SSteven Eckhoff };
1499ba6c2959SSteven Eckhoff MODULE_DEVICE_TABLE(of, tscs42xx_of_match);
1500ba6c2959SSteven Eckhoff 
1501ba6c2959SSteven Eckhoff static struct i2c_driver tscs42xx_i2c_driver = {
1502ba6c2959SSteven Eckhoff 	.driver = {
1503ba6c2959SSteven Eckhoff 		.name = "tscs42xx",
1504ba6c2959SSteven Eckhoff 		.of_match_table = tscs42xx_of_match,
1505ba6c2959SSteven Eckhoff 	},
1506*9abcd240SUwe Kleine-König 	.probe = tscs42xx_i2c_probe,
1507ba6c2959SSteven Eckhoff 	.id_table = tscs42xx_i2c_id,
1508ba6c2959SSteven Eckhoff };
1509ba6c2959SSteven Eckhoff 
1510ba6c2959SSteven Eckhoff module_i2c_driver(tscs42xx_i2c_driver);
1511ba6c2959SSteven Eckhoff 
1512ba6c2959SSteven Eckhoff MODULE_AUTHOR("Tempo Semiconductor <steven.eckhoff.opensource@gmail.com");
1513ba6c2959SSteven Eckhoff MODULE_DESCRIPTION("ASoC TSCS42xx driver");
1514ba6c2959SSteven Eckhoff MODULE_LICENSE("GPL");
1515