View | Details | Raw Unified | Return to bug 36374
Collapse All | Expand All

(-)linux-4.20/Documentation/devicetree/bindings/sound/cx2072x.txt (+36 lines)
Line 0 Link Here
1
Conexant CX20721/CX20723/CX7601 audio CODEC
2
3
The devices support I2C only.
4
5
Required properties:
6
7
  - compatible : One of "cnxt,cx20721", "cnxt,cx20723", "cnxt,cx7601".
8
9
  - reg : the I2C address of the device for I2C, it should be <0x33>
10
11
Optional properties:
12
13
  - clocks : phandle and clock specifier for codec MCLK.
14
  - clock-names : Clock name string for 'clocks' attribute, should be "mclk".
15
16
CODEC output pins:
17
  "PORTA"	- Headphone
18
  "PORTG"	- Class-D output
19
  "PORTE"	- Line out
20
21
CODEC output pins for Conexant DSP chip:
22
  "AEC REF"	- AEC reference signal
23
24
CODEC input pins:
25
  "PORTB"	- Analog mic
26
  "PORTC"	- Digital mic
27
  "PORTD"	- Headset mic
28
29
Example:
30
31
codec: cx20721@33 {
32
	compatible = "cnxt,cx20721";
33
	reg = <0x33>;
34
	clocks = <&sco>;
35
	clock-names = "mclk";
36
};
(-)linux-4.20/sound/soc/codecs/Kconfig (+5 lines)
Lines 68-73 Link Here
68
	select SND_SOC_CS47L24 if MFD_CS47L24
68
	select SND_SOC_CS47L24 if MFD_CS47L24
69
	select SND_SOC_CS53L30 if I2C
69
	select SND_SOC_CS53L30 if I2C
70
	select SND_SOC_CX20442 if TTY
70
	select SND_SOC_CX20442 if TTY
71
	select SND_SOC_CX2072X if I2C
71
	select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
72
	select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
72
	select SND_SOC_DA7213 if I2C
73
	select SND_SOC_DA7213 if I2C
73
	select SND_SOC_DA7218 if I2C
74
	select SND_SOC_DA7218 if I2C
Lines 553-558 Link Here
553
	tristate
554
	tristate
554
	depends on TTY
555
	depends on TTY
555
556
557
config SND_SOC_CX2072X
558
	tristate "Conexant CX2072X CODEC"
559
	depends on I2C
560
556
config SND_SOC_JZ4740_CODEC
561
config SND_SOC_JZ4740_CODEC
557
	select REGMAP_MMIO
562
	select REGMAP_MMIO
558
	tristate
563
	tristate
(-)linux-4.20/sound/soc/codecs/Makefile (+2 lines)
Lines 63-68 Link Here
63
snd-soc-cs47l24-objs := cs47l24.o
63
snd-soc-cs47l24-objs := cs47l24.o
64
snd-soc-cs53l30-objs := cs53l30.o
64
snd-soc-cs53l30-objs := cs53l30.o
65
snd-soc-cx20442-objs := cx20442.o
65
snd-soc-cx20442-objs := cx20442.o
66
snd-soc-cx2072x-objs := cx2072x.o
66
snd-soc-da7210-objs := da7210.o
67
snd-soc-da7210-objs := da7210.o
67
snd-soc-da7213-objs := da7213.o
68
snd-soc-da7213-objs := da7213.o
68
snd-soc-da7218-objs := da7218.o
69
snd-soc-da7218-objs := da7218.o
Lines 328-333 Link Here
328
obj-$(CONFIG_SND_SOC_CS47L24)	+= snd-soc-cs47l24.o
329
obj-$(CONFIG_SND_SOC_CS47L24)	+= snd-soc-cs47l24.o
329
obj-$(CONFIG_SND_SOC_CS53L30)	+= snd-soc-cs53l30.o
330
obj-$(CONFIG_SND_SOC_CS53L30)	+= snd-soc-cs53l30.o
330
obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
331
obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
332
obj-$(CONFIG_SND_SOC_CX2072X)	+= snd-soc-cx2072x.o
331
obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
333
obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
332
obj-$(CONFIG_SND_SOC_DA7213)	+= snd-soc-da7213.o
334
obj-$(CONFIG_SND_SOC_DA7213)	+= snd-soc-da7213.o
333
obj-$(CONFIG_SND_SOC_DA7218)	+= snd-soc-da7218.o
335
obj-$(CONFIG_SND_SOC_DA7218)	+= snd-soc-da7218.o
(-)linux-4.20/sound/soc/codecs/cx2072x.c (+2263 lines)
Line 0 Link Here
1
/*
2
 * ALSA SoC CX20721/CX20723 codec driver
3
 *
4
 * Copyright:	(C) 2017 Conexant Systems, Inc.
5
 * Author:	Simon Ho, <Simon.ho@conexant.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 *
11
 * TODO: add support for TDM mode.
12
 */
13
14
#include <linux/module.h>
15
#include <linux/moduleparam.h>
16
#include <linux/init.h>
17
#include <linux/delay.h>
18
#include <linux/pm.h>
19
#include <linux/platform_device.h>
20
#include <linux/of_gpio.h>
21
#include <linux/gpio.h>
22
#include <linux/slab.h>
23
#include <linux/i2c.h>
24
#include <linux/firmware.h>
25
#include <linux/regmap.h>
26
#include <linux/proc_fs.h>
27
#include <linux/interrupt.h>
28
#include <linux/irq.h>
29
#include <linux/clk.h>
30
#include <linux/acpi.h>
31
#include <sound/core.h>
32
#include <sound/pcm.h>
33
#include <sound/pcm_params.h>
34
#include <sound/soc.h>
35
#include <sound/soc-dapm.h>
36
#include <sound/initval.h>
37
#include <sound/tlv.h>
38
#include <sound/jack.h>
39
#include "cx2072x.h"
40
41
#define PLL_OUT_HZ_48 (1024 * 3 * 48000)
42
#define BITS_PER_SLOT 8
43
44
#define CX2072X_PLBK_EQ_BAND_NUM 7
45
#define CX2072X_PLBK_EQ_COEF_LEN 11
46
#define CX2072X_PLBK_DRC_PARM_LEN 9
47
#define CX2072X_CLASSD_AMP_LEN 6
48
49
/* codec private data */
50
struct cx2072x_priv {
51
	struct regmap *regmap;
52
	struct clk *mclk;
53
	unsigned int mclk_rate;
54
	struct device *dev;
55
	struct snd_soc_component *component;
56
	struct snd_soc_dai_driver *dai_drv;
57
	int is_biason;
58
	struct snd_soc_jack *jack;
59
	bool jack_detecting;
60
	bool jack_mic;
61
	int jack_mode;
62
	int jack_flips;
63
	unsigned int jack_state;
64
	int audsmt_enable;
65
	unsigned int bclk_ratio;
66
	bool plbk_eq_en;
67
	bool plbk_eq_en_changed;
68
	bool plbk_eq_changed;
69
	u8 plbk_eq[2][CX2072X_PLBK_EQ_BAND_NUM][CX2072X_PLBK_EQ_COEF_LEN];
70
	int plbk_eq_channel;
71
	bool plbk_drc_en;
72
	bool plbk_drc_en_changed;
73
	bool plbk_drc_changed;
74
	bool pll_changed;
75
	bool i2spcm_changed;
76
	int sample_size;
77
	int frame_size;
78
	int sample_rate;
79
	unsigned int dai_fmt;
80
	int tdm_rx_mask;
81
	int tdm_tx_mask;
82
	int tdm_slot_width;
83
	int tdm_slots;
84
	u32 rev_id;
85
	bool en_aec_ref;
86
	u8 plbk_drc[CX2072X_PLBK_DRC_PARM_LEN];
87
	u8 classd_amp[CX2072X_CLASSD_AMP_LEN];
88
	struct mutex eq_coeff_lock; /* EQ DSP lock */
89
};
90
91
/*
92
 * DAC/ADC Volume
93
 *
94
 * max : 74 : 0 dB
95
 *	 ( in 1 dB  step )
96
 * min : 0 : -74 dB
97
 */
98
static const DECLARE_TLV_DB_SCALE(adc_tlv, -7400, 100, 0);
99
static const DECLARE_TLV_DB_SCALE(dac_tlv, -7400, 100, 0);
100
static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 1200, 0);
101
102
struct CX2072X_EQ_CTRL {
103
	u8 ch;
104
	u8 band;
105
};
106
107
static DECLARE_TLV_DB_RANGE(hpf_tlv,
108
		0, 0, TLV_DB_SCALE_ITEM(120, 0, 0),
109
		1, 63, TLV_DB_SCALE_ITEM(30, 30, 0)
110
);
111
112
/* Lookup table for PRE_DIV*/
113
static struct {
114
	unsigned int mclk;
115
	unsigned int div;
116
} MCLK_PRE_DIV[] = {
117
	{ 6144000, 1 },
118
	{ 12288000, 2 },
119
	{ 19200000, 3 },
120
	{ 26000000, 4 },
121
	{ 28224000, 5 },
122
	{ 36864000, 6 },
123
	{ 36864000, 7 },
124
	{ 48000000, 8 },
125
	{ 49152000, 8 },
126
};
127
128
/*
129
 * cx2072x register cache.
130
 */
131
static const struct reg_default cx2072x_reg_defaults[] = {
132
	{ CX2072X_AFG_POWER_STATE, 0x00000003 },
133
	{ CX2072X_UM_RESPONSE, 0x00000000 },
134
	{ CX2072X_GPIO_DATA, 0x00000000 },
135
	{ CX2072X_GPIO_ENABLE, 0x00000000 },
136
	{ CX2072X_GPIO_DIRECTION, 0x00000000 },
137
	{ CX2072X_GPIO_WAKE, 0x00000000 },
138
	{ CX2072X_GPIO_UM_ENABLE, 0x00000000 },
139
	{ CX2072X_GPIO_STICKY_MASK, 0x00000000 },
140
	{ CX2072X_DAC1_CONVERTER_FORMAT, 0x00000031 },
141
	{ CX2072X_DAC1_AMP_GAIN_RIGHT, 0x0000004a },
142
	{ CX2072X_DAC1_AMP_GAIN_LEFT, 0x0000004a },
143
	{ CX2072X_DAC1_POWER_STATE, 0x00000433 },
144
	{ CX2072X_DAC1_CONVERTER_STREAM_CHANNEL, 0x00000000 },
145
	{ CX2072X_DAC1_EAPD_ENABLE, 0x00000000 },
146
	{ CX2072X_DAC2_CONVERTER_FORMAT, 0x00000031 },
147
	{ CX2072X_DAC2_AMP_GAIN_RIGHT, 0x0000004a },
148
	{ CX2072X_DAC2_AMP_GAIN_LEFT, 0x0000004a },
149
	{ CX2072X_DAC2_POWER_STATE, 0x00000433 },
150
	{ CX2072X_DAC2_CONVERTER_STREAM_CHANNEL, 0x00000000 },
151
	{ CX2072X_ADC1_CONVERTER_FORMAT, 0x00000031 },
152
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_0, 0x0000004a },
153
	{ CX2072X_ADC1_AMP_GAIN_LEFT_0, 0x0000004a },
154
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_1, 0x0000004a },
155
	{ CX2072X_ADC1_AMP_GAIN_LEFT_1, 0x0000004a },
156
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_2, 0x0000004a },
157
	{ CX2072X_ADC1_AMP_GAIN_LEFT_2, 0x0000004a },
158
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_3, 0x0000004a },
159
	{ CX2072X_ADC1_AMP_GAIN_LEFT_3, 0x0000004a },
160
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_4, 0x0000004a },
161
	{ CX2072X_ADC1_AMP_GAIN_LEFT_4, 0x0000004a },
162
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_5, 0x0000004a },
163
	{ CX2072X_ADC1_AMP_GAIN_LEFT_5, 0x0000004a },
164
	{ CX2072X_ADC1_AMP_GAIN_RIGHT_6, 0x0000004a },
165
	{ CX2072X_ADC1_AMP_GAIN_LEFT_6, 0x0000004a },
166
	{ CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 0x00000000 },
167
	{ CX2072X_ADC1_POWER_STATE, 0x00000433 },
168
	{ CX2072X_ADC1_CONVERTER_STREAM_CHANNEL, 0x00000000 },
169
	{ CX2072X_ADC2_CONVERTER_FORMAT, 0x00000031 },
170
	{ CX2072X_ADC2_AMP_GAIN_RIGHT_0, 0x0000004a },
171
	{ CX2072X_ADC2_AMP_GAIN_LEFT_0, 0x0000004a },
172
	{ CX2072X_ADC2_AMP_GAIN_RIGHT_1, 0x0000004a },
173
	{ CX2072X_ADC2_AMP_GAIN_LEFT_1, 0x0000004a },
174
	{ CX2072X_ADC2_AMP_GAIN_RIGHT_2, 0x0000004a },
175
	{ CX2072X_ADC2_AMP_GAIN_LEFT_2, 0x0000004a },
176
	{ CX2072X_ADC2_CONNECTION_SELECT_CONTROL, 0x00000000 },
177
	{ CX2072X_ADC2_POWER_STATE, 0x00000433 },
178
	{ CX2072X_ADC2_CONVERTER_STREAM_CHANNEL, 0x00000000 },
179
	{ CX2072X_PORTA_CONNECTION_SELECT_CTRL, 0x00000000 },
180
	{ CX2072X_PORTA_POWER_STATE, 0x00000433 },
181
	{ CX2072X_PORTA_PIN_CTRL, 0x000000c0 },
182
	{ CX2072X_PORTA_UNSOLICITED_RESPONSE, 0x00000000 },
183
	{ CX2072X_PORTA_PIN_SENSE, 0x00000000 },
184
	{ CX2072X_PORTA_EAPD_BTL, 0x00000002 },
185
	{ CX2072X_PORTB_POWER_STATE, 0x00000433 },
186
	{ CX2072X_PORTB_PIN_CTRL, 0x00000000 },
187
	{ CX2072X_PORTB_UNSOLICITED_RESPONSE, 0x00000000 },
188
	{ CX2072X_PORTB_PIN_SENSE, 0x00000000 },
189
	{ CX2072X_PORTB_EAPD_BTL, 0x00000002 },
190
	{ CX2072X_PORTB_GAIN_RIGHT, 0x00000000 },
191
	{ CX2072X_PORTB_GAIN_LEFT, 0x00000000 },
192
	{ CX2072X_PORTC_POWER_STATE, 0x00000433 },
193
	{ CX2072X_PORTC_PIN_CTRL, 0x00000000 },
194
	{ CX2072X_PORTC_GAIN_RIGHT, 0x00000000 },
195
	{ CX2072X_PORTC_GAIN_LEFT, 0x00000000 },
196
	{ CX2072X_PORTD_POWER_STATE, 0x00000433 },
197
	{ CX2072X_PORTD_PIN_CTRL, 0x00000020 },
198
	{ CX2072X_PORTD_UNSOLICITED_RESPONSE, 0x00000000 },
199
	{ CX2072X_PORTD_PIN_SENSE, 0x00000000 },
200
	{ CX2072X_PORTD_GAIN_RIGHT, 0x00000000 },
201
	{ CX2072X_PORTD_GAIN_LEFT, 0x00000000 },
202
	{ CX2072X_PORTE_CONNECTION_SELECT_CTRL, 0x00000000 },
203
	{ CX2072X_PORTE_POWER_STATE, 0x00000433 },
204
	{ CX2072X_PORTE_PIN_CTRL, 0x00000040 },
205
	{ CX2072X_PORTE_UNSOLICITED_RESPONSE, 0x00000000 },
206
	{ CX2072X_PORTE_PIN_SENSE, 0x00000000 },
207
	{ CX2072X_PORTE_EAPD_BTL, 0x00000002 },
208
	{ CX2072X_PORTE_GAIN_RIGHT, 0x00000000 },
209
	{ CX2072X_PORTE_GAIN_LEFT, 0x00000000 },
210
	{ CX2072X_PORTF_POWER_STATE, 0x00000433 },
211
	{ CX2072X_PORTF_PIN_CTRL, 0x00000000 },
212
	{ CX2072X_PORTF_UNSOLICITED_RESPONSE, 0x00000000 },
213
	{ CX2072X_PORTF_PIN_SENSE, 0x00000000 },
214
	{ CX2072X_PORTF_GAIN_RIGHT, 0x00000000 },
215
	{ CX2072X_PORTF_GAIN_LEFT, 0x00000000 },
216
	{ CX2072X_PORTG_POWER_STATE, 0x00000433 },
217
	{ CX2072X_PORTG_PIN_CTRL, 0x00000040 },
218
	{ CX2072X_PORTG_CONNECTION_SELECT_CTRL, 0x00000000 },
219
	{ CX2072X_PORTG_EAPD_BTL, 0x00000002 },
220
	{ CX2072X_PORTM_POWER_STATE, 0x00000433 },
221
	{ CX2072X_PORTM_PIN_CTRL, 0x00000000 },
222
	{ CX2072X_PORTM_CONNECTION_SELECT_CTRL, 0x00000000 },
223
	{ CX2072X_PORTM_EAPD_BTL, 0x00000002 },
224
	{ CX2072X_MIXER_POWER_STATE, 0x00000433 },
225
	{ CX2072X_MIXER_GAIN_RIGHT_0, 0x0000004a },
226
	{ CX2072X_MIXER_GAIN_LEFT_0, 0x0000004a },
227
	{ CX2072X_MIXER_GAIN_RIGHT_1, 0x0000004a },
228
	{ CX2072X_MIXER_GAIN_LEFT_1, 0x0000004a },
229
	{ CX2072X_SPKR_DRC_ENABLE_STEP, 0x040065a4 },
230
	{ CX2072X_SPKR_DRC_CONTROL, 0x007b0024 },
231
	{ CX2072X_SPKR_DRC_TEST, 0x00000000 },
232
	{ CX2072X_DIGITAL_BIOS_TEST0, 0x001f008a },
233
	{ CX2072X_DIGITAL_BIOS_TEST2, 0x00990026 },
234
	{ CX2072X_I2SPCM_CONTROL1, 0x00010001 },
235
	{ CX2072X_I2SPCM_CONTROL2, 0x00000000 },
236
	{ CX2072X_I2SPCM_CONTROL3, 0x00000000 },
237
	{ CX2072X_I2SPCM_CONTROL4, 0x00000000 },
238
	{ CX2072X_I2SPCM_CONTROL5, 0x00000000 },
239
	{ CX2072X_I2SPCM_CONTROL6, 0x00000000 },
240
	{ CX2072X_UM_INTERRUPT_CRTL_E, 0x00000000 },
241
	{ CX2072X_CODEC_TEST2, 0x00000000 },
242
	{ CX2072X_CODEC_TEST9, 0x00000004 },
243
	{ CX2072X_CODEC_TEST20, 0x00000600 },
244
	{ CX2072X_CODEC_TEST26, 0x00000208 },
245
	{ CX2072X_ANALOG_TEST4, 0x00000000 },
246
	{ CX2072X_ANALOG_TEST5, 0x00000000 },
247
	{ CX2072X_ANALOG_TEST6, 0x0000059a },
248
	{ CX2072X_ANALOG_TEST7, 0x000000a7 },
249
	{ CX2072X_ANALOG_TEST8, 0x00000017 },
250
	{ CX2072X_ANALOG_TEST9, 0x00000000 },
251
	{ CX2072X_ANALOG_TEST10, 0x00000285 },
252
	{ CX2072X_ANALOG_TEST11, 0x00000000 },
253
	{ CX2072X_ANALOG_TEST12, 0x00000000 },
254
	{ CX2072X_ANALOG_TEST13, 0x00000000 },
255
	{ CX2072X_DIGITAL_TEST1, 0x00000242 },
256
	{ CX2072X_DIGITAL_TEST11, 0x00000000 },
257
	{ CX2072X_DIGITAL_TEST12, 0x00000084 },
258
	{ CX2072X_DIGITAL_TEST15, 0x00000077 },
259
	{ CX2072X_DIGITAL_TEST16, 0x00000021 },
260
	{ CX2072X_DIGITAL_TEST17, 0x00000018 },
261
	{ CX2072X_DIGITAL_TEST18, 0x00000024 },
262
	{ CX2072X_DIGITAL_TEST19, 0x00000001 },
263
	{ CX2072X_DIGITAL_TEST20, 0x00000002 },
264
};
265
266
/*
267
 * register patch.
268
 */
269
static const struct reg_sequence cx2072x_patch[] = {
270
	{ 0x71A4, 0x080 }, /* DC offset Calibration	   */
271
	{ 0x71a8, 0x287 }, /* Set max spk power to 1.5 W   */
272
	{ 0x7328, 0xa8c }, /* Set average spk power to 1.5W*/
273
	{ 0x7310, 0xf01 }, /*				   */
274
	{ 0x7328, 0xa8f }, /*				   */
275
	{ 0x7124, 0x001 }, /* Enable 30 Hz High pass filter*/
276
	{ 0x718c, 0x300 }, /* Disable PCBEEP pad	   */
277
	{ 0x731c, 0x100 }, /* Disable SnM mode		   */
278
	{ 0x641c, 0x020 }, /* Enable PortD input	   */
279
	{ 0x0458, 0x040 }, /* Enable GPIO7 pin for button  */
280
	{ 0x0464, 0x040 }, /* Enable UM for GPIO7	   */
281
	{ 0x0420, 0x080 }, /* Enable button response	   */
282
	{ 0x7230, 0x0c4 }, /* Enable headset button	   */
283
	{ 0x7200, 0x415 }, /* Power down class-d during idle*/
284
	{ 0x6e04, 0x00f }, /* Enable I2S tx                */
285
	{ 0x6e08, 0x00f }, /* Enable I2S rx                */
286
};
287
288
/* return register size */
289
static unsigned int cx2072x_register_size(struct device *dev, unsigned int reg)
290
{
291
	switch (reg) {
292
	case CX2072X_VENDOR_ID:
293
	case CX2072X_REVISION_ID:
294
	case CX2072X_PORTA_PIN_SENSE:
295
	case CX2072X_PORTB_PIN_SENSE:
296
	case CX2072X_PORTD_PIN_SENSE:
297
	case CX2072X_PORTE_PIN_SENSE:
298
	case CX2072X_PORTF_PIN_SENSE:
299
	case CX2072X_I2SPCM_CONTROL1:
300
	case CX2072X_I2SPCM_CONTROL2:
301
	case CX2072X_I2SPCM_CONTROL3:
302
	case CX2072X_I2SPCM_CONTROL4:
303
	case CX2072X_I2SPCM_CONTROL5:
304
	case CX2072X_I2SPCM_CONTROL6:
305
	case CX2072X_UM_INTERRUPT_CRTL_E:
306
	case CX2072X_EQ_G_COEFF:
307
	case CX2072X_SPKR_DRC_CONTROL:
308
	case CX2072X_SPKR_DRC_TEST:
309
	case CX2072X_DIGITAL_BIOS_TEST0:
310
	case CX2072X_DIGITAL_BIOS_TEST2:
311
		return 4;
312
	case CX2072X_EQ_ENABLE_BYPASS:
313
	case CX2072X_EQ_B0_COEFF:
314
	case CX2072X_EQ_B1_COEFF:
315
	case CX2072X_EQ_B2_COEFF:
316
	case CX2072X_EQ_A1_COEFF:
317
	case CX2072X_EQ_A2_COEFF:
318
	case CX2072X_DAC1_CONVERTER_FORMAT:
319
	case CX2072X_DAC2_CONVERTER_FORMAT:
320
	case CX2072X_ADC1_CONVERTER_FORMAT:
321
	case CX2072X_ADC2_CONVERTER_FORMAT:
322
	case CX2072X_CODEC_TEST2:
323
	case CX2072X_CODEC_TEST9:
324
	case CX2072X_CODEC_TEST20:
325
	case CX2072X_CODEC_TEST26:
326
	case CX2072X_ANALOG_TEST3:
327
	case CX2072X_ANALOG_TEST4:
328
	case CX2072X_ANALOG_TEST5:
329
	case CX2072X_ANALOG_TEST6:
330
	case CX2072X_ANALOG_TEST7:
331
	case CX2072X_ANALOG_TEST8:
332
	case CX2072X_ANALOG_TEST9:
333
	case CX2072X_ANALOG_TEST10:
334
	case CX2072X_ANALOG_TEST11:
335
	case CX2072X_ANALOG_TEST12:
336
	case CX2072X_ANALOG_TEST13:
337
	case CX2072X_DIGITAL_TEST0:
338
	case CX2072X_DIGITAL_TEST1:
339
	case CX2072X_DIGITAL_TEST11:
340
	case CX2072X_DIGITAL_TEST12:
341
	case CX2072X_DIGITAL_TEST15:
342
	case CX2072X_DIGITAL_TEST16:
343
	case CX2072X_DIGITAL_TEST17:
344
	case CX2072X_DIGITAL_TEST18:
345
	case CX2072X_DIGITAL_TEST19:
346
	case CX2072X_DIGITAL_TEST20:
347
		return 2;
348
	default:
349
		return 1;
350
	}
351
}
352
353
static int cx2072x_reg_write(void *context, unsigned int reg,
354
			     unsigned int value)
355
{
356
	struct i2c_client *client = context;
357
	unsigned int i;
358
	unsigned int size;
359
	u8 buf[6];
360
	int ret;
361
	struct device *dev = &client->dev;
362
363
	size = cx2072x_register_size(dev, reg);
364
	if (size == 0)
365
		return -EINVAL;
366
367
	if (reg == CX2072X_UM_INTERRUPT_CRTL_E) {
368
		/* Update the MSB byte only */
369
		reg += 3;
370
		size = 1;
371
		value >>= 24;
372
	}
373
374
	buf[0] = reg >> 8;
375
	buf[1] = reg & 0xff;
376
377
	for (i = 2; i < (size + 2); ++i) {
378
		buf[i] = value;
379
		value >>= 8;
380
	}
381
382
	ret = i2c_master_send(client, buf, size + 2);
383
	if (ret == size + 2) {
384
		ret =  0;
385
	} else if (ret < 0) {
386
		dev_err(dev, "I2C write address failed, error = %d\n", ret);
387
	} else {
388
		dev_err(dev, "I2C write failed\n");
389
		ret =  -EIO;
390
	}
391
	return ret;
392
}
393
394
static int cx2072x_reg_bulk_write(struct snd_soc_component *component, unsigned int reg,
395
				  const void *val, size_t val_count)
396
{
397
	struct i2c_client *client = to_i2c_client(component->dev);
398
	u8 buf[2 + MAX_EQ_COEFF];
399
	int ret;
400
	struct device *dev = &client->dev;
401
402
	if (val_count > MAX_EQ_COEFF) {
403
		dev_err(dev,
404
			"cx2072x_reg_bulk_write failed, writing count = %d\n",
405
			(int)val_count);
406
		return -EINVAL;
407
	}
408
409
	buf[0] = reg >> 8;
410
	buf[1] = reg & 0xff;
411
412
	memcpy(&buf[2], val, val_count);
413
414
	ret = i2c_master_send(client, buf, val_count + 2);
415
	if (ret == val_count + 2) {
416
		return 0;
417
	} else if (ret < 0) {
418
		dev_err(dev,
419
			"I2C bulk write address failed\n");
420
	} else {
421
		dev_err(dev,
422
			"I2C bulk write address failed\n");
423
		ret = -EIO;
424
	}
425
	return ret;
426
}
427
428
static int cx2072x_reg_read(void *context, unsigned int reg,
429
			    unsigned int *value)
430
{
431
	int ret;
432
	unsigned int size;
433
	u8 send_buf[2];
434
	unsigned int recv_buf = 0;
435
	struct i2c_client *client = context;
436
	struct i2c_msg msgs[2];
437
	struct device *dev = &client->dev;
438
439
	size = cx2072x_register_size(dev, reg);
440
	if (size == 0)
441
		return -EINVAL;
442
443
	send_buf[0] = reg >> 8;
444
	send_buf[1] = reg & 0xff;
445
446
	msgs[0].addr = client->addr;
447
	msgs[0].len = sizeof(send_buf);
448
	msgs[0].buf = send_buf;
449
	msgs[0].flags = 0;
450
451
	msgs[1].addr = client->addr;
452
	msgs[1].len = size;
453
	msgs[1].buf = (u8 *)&recv_buf;
454
	msgs[1].flags = I2C_M_RD;
455
456
	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
457
	if (ret < 0) {
458
		dev_err(dev,
459
			"Failed to register codec: %d\n", ret);
460
		return ret;
461
	} else if (ret != ARRAY_SIZE(msgs)) {
462
		dev_err(dev,
463
			"Failed to register codec: %d\n", ret);
464
		return -EIO;
465
	}
466
467
	*value = recv_buf;
468
469
	return 0;
470
}
471
472
/* get suggested pre_div valuce from mclk frequency */
473
static unsigned int get_div_from_mclk(unsigned int mclk)
474
{
475
	unsigned int div = 8;
476
	int i = 0;
477
478
	for (i = 0; i < ARRAY_SIZE(MCLK_PRE_DIV); i++) {
479
		if (mclk <= MCLK_PRE_DIV[i].mclk) {
480
			div = MCLK_PRE_DIV[i].div;
481
			break;
482
		}
483
	}
484
	return div;
485
}
486
487
static int cx2072x_config_pll(struct cx2072x_priv *cx2072x)
488
{
489
	struct device *dev = cx2072x->dev;
490
	unsigned int pre_div;
491
	unsigned int pre_div_val;
492
	unsigned int pll_input;
493
	unsigned int pll_output;
494
	unsigned int int_div;
495
	unsigned int frac_div;
496
	u64 frac_num;
497
	unsigned int frac;
498
	unsigned int sample_rate = cx2072x->sample_rate;
499
	int pt_sample_per_sync = 2;
500
	int pt_clock_per_sample = 96;
501
502
	switch (sample_rate) {
503
	case 48000:
504
	case 32000:
505
	case 24000:
506
	case 16000:
507
		break;
508
509
	case 96000:
510
		pt_sample_per_sync = 1;
511
		pt_clock_per_sample = 48;
512
		break;
513
514
	case 192000:
515
		pt_sample_per_sync = 0;
516
		pt_clock_per_sample = 24;
517
		break;
518
519
	default:
520
		dev_err(dev, "Unsupported sample rate %d\n", sample_rate);
521
		return -EINVAL;
522
	}
523
524
	/*Configure PLL settings*/
525
	pre_div = get_div_from_mclk(cx2072x->mclk_rate);
526
	pll_input = cx2072x->mclk_rate / pre_div;
527
	pll_output = sample_rate * 3072;
528
	int_div = pll_output / pll_input;
529
	frac_div = pll_output - (int_div * pll_input);
530
531
	if (frac_div) {
532
		frac_div *= 1000;
533
		frac_div /= pll_input;
534
		frac_num = ((4000 + frac_div) * ((1 << 20) - 4));
535
		do_div(frac_num, 7);
536
		frac = ((u32)frac_num + 499) / 1000;
537
	}
538
	pre_div_val = (pre_div - 1) * 2;
539
540
	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST4, 0X40
541
		| (pre_div_val << 8));
542
	if (frac_div == 0) {
543
		/*Int mode*/
544
		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7, 0x100);
545
	} else {
546
		/*frac mode*/
547
		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST6,
548
			     frac & 0xfff);
549
		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7,
550
			     (u8)(frac >> 12));
551
	}
552
553
	int_div--;
554
	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST8, int_div);
555
556
	/* configure PLL tracking*/
557
	if (frac_div == 0) {
558
		/* disable PLL tracking*/
559
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16, 0x00);
560
	} else {
561
		/* configure and enable PLL tracking*/
562
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16,
563
			     (pt_sample_per_sync << 4) & 0xf0);
564
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST17,
565
			     pt_clock_per_sample);
566
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST18,
567
			     pt_clock_per_sample * 3 / 2);
568
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST19, 0x01);
569
		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST20, 0x02);
570
		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_TEST16,
571
				   0X01, 0X01);
572
	}
573
574
	return 0;
575
}
576
577
static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x)
578
{
579
	struct device *dev = cx2072x->dev;
580
	unsigned int bclk_rate = 0;
581
	int is_i2s = 0;
582
	int has_one_bit_delay = 0;
583
	int is_right_j = 0;
584
	int is_frame_inv = 0;
585
	int is_bclk_inv = 0;
586
	int pulse_len = 1;
587
	int frame_len = cx2072x->frame_size;
588
	int sample_size = cx2072x->sample_size;
589
	int i2s_right_slot;
590
	int i2s_right_pause_interval = 0;
591
	int i2s_right_pause_pos;
592
	int is_big_endian = 1;
593
	u64 div;
594
	unsigned int mod;
595
	union REG_I2SPCM_CTRL_REG1 reg1;
596
	union REG_I2SPCM_CTRL_REG2 reg2;
597
	union REG_I2SPCM_CTRL_REG3 reg3;
598
	union REG_I2SPCM_CTRL_REG4 reg4;
599
	union REG_I2SPCM_CTRL_REG5 reg5;
600
	union REG_I2SPCM_CTRL_REG6 reg6;
601
	union REG_DIGITAL_BIOS_TEST2 regdbt2;
602
	const unsigned int fmt = cx2072x->dai_fmt;
603
604
	if (frame_len <= 0) {
605
		dev_err(dev, "Incorrect frame len %d\n", frame_len);
606
		return -EINVAL;
607
	}
608
609
	if (sample_size <= 0) {
610
		dev_err(dev, "Incorrect sample size %d\n", sample_size);
611
		return -EINVAL;
612
	}
613
614
	dev_dbg(dev, "config_i2spcm set_dai_fmt- %08x\n", fmt);
615
616
	regdbt2.ulval = 0xac;
617
618
	/* set master/slave */
619
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
620
	case SND_SOC_DAIFMT_CBM_CFM:
621
		reg2.r.tx_master = 1;
622
		reg3.r.rx_master = 1;
623
		dev_dbg(dev, "Sets Master mode\n");
624
		break;
625
626
	case SND_SOC_DAIFMT_CBS_CFS:
627
		reg2.r.tx_master = 0;
628
		reg3.r.rx_master = 0;
629
		dev_dbg(dev, "Sets Slave mode\n");
630
		break;
631
632
	default:
633
		dev_err(dev, "Unsupported DAI master mode\n");
634
		return -EINVAL;
635
	}
636
637
	/* set format */
638
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
639
	case SND_SOC_DAIFMT_I2S:
640
		is_i2s = 1;
641
		has_one_bit_delay = 1;
642
		pulse_len = frame_len / 2;
643
		break;
644
645
	case SND_SOC_DAIFMT_RIGHT_J:
646
		is_i2s = 1;
647
		is_right_j = 1;
648
		pulse_len = frame_len / 2;
649
		break;
650
651
	case SND_SOC_DAIFMT_LEFT_J:
652
		is_i2s = 1;
653
		pulse_len = frame_len / 2;
654
		break;
655
656
	default:
657
		dev_err(dev, "Unsupported DAI format\n");
658
		return -EINVAL;
659
	}
660
661
	/* clock inversion */
662
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
663
	case SND_SOC_DAIFMT_NB_NF:
664
		is_frame_inv = is_i2s;
665
		is_bclk_inv = is_i2s;
666
		break;
667
668
	case SND_SOC_DAIFMT_IB_IF:
669
		is_frame_inv = !is_i2s;
670
		is_bclk_inv = !is_i2s;
671
		break;
672
673
	case SND_SOC_DAIFMT_IB_NF:
674
		is_frame_inv = is_i2s;
675
		is_bclk_inv = !is_i2s;
676
		break;
677
678
	case SND_SOC_DAIFMT_NB_IF:
679
		is_frame_inv = !is_i2s;
680
		is_bclk_inv = is_i2s;
681
		break;
682
683
	default:
684
		dev_err(dev, "Unsupported DAI clock inversion\n");
685
		return -EINVAL;
686
	}
687
688
	reg1.r.rx_data_one_line = 1;
689
	reg1.r.tx_data_one_line = 1;
690
691
	if (is_i2s) {
692
		i2s_right_slot = (frame_len / 2) / BITS_PER_SLOT;
693
		i2s_right_pause_interval = (frame_len / 2) % BITS_PER_SLOT;
694
		i2s_right_pause_pos = i2s_right_slot * BITS_PER_SLOT;
695
	}
696
697
	reg1.r.rx_ws_pol = is_frame_inv;
698
	reg1.r.rx_ws_wid = pulse_len - 1;
699
700
	reg1.r.rx_frm_len = frame_len / BITS_PER_SLOT - 1;
701
	reg1.r.rx_sa_size = (sample_size / BITS_PER_SLOT) - 1;
702
703
	reg1.r.tx_ws_pol = reg1.r.rx_ws_pol;
704
	reg1.r.tx_ws_wid = pulse_len - 1;
705
	reg1.r.tx_frm_len = reg1.r.rx_frm_len;
706
	reg1.r.tx_sa_size = reg1.r.rx_sa_size;
707
708
	reg2.r.tx_endian_sel = !is_big_endian;
709
	reg2.r.tx_dstart_dly = has_one_bit_delay;
710
711
	reg3.r.rx_endian_sel = !is_big_endian;
712
	reg3.r.rx_dstart_dly = has_one_bit_delay;
713
714
	reg4.ulval = 0;
715
716
	if (is_i2s) {
717
		reg2.r.tx_slot_1 = 0;
718
		reg2.r.tx_slot_2 = i2s_right_slot;
719
		reg3.r.rx_slot_1 = 0;
720
		reg3.r.rx_slot_2 = i2s_right_slot;
721
		reg6.r.rx_pause_start_pos = i2s_right_pause_pos;
722
		reg6.r.rx_pause_cycles = i2s_right_pause_interval;
723
		reg6.r.tx_pause_start_pos = i2s_right_pause_pos;
724
		reg6.r.tx_pause_cycles = i2s_right_pause_interval;
725
	} else {
726
		dev_err(dev, "TDM mode is not implemented yet\n");
727
		return -EINVAL;
728
	}
729
	regdbt2.r.i2s_bclk_invert = is_bclk_inv;
730
731
	reg1.r.rx_data_one_line = 1;
732
	reg1.r.tx_data_one_line = 1;
733
734
	/* Configures the BCLK output.*/
735
	bclk_rate = cx2072x->sample_rate * frame_len;
736
	reg5.r.i2s_pcm_clk_div_chan_en = 0;
737
738
	/*Disables bclk output before setting new value*/
739
	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL5, 0);
740
741
	if (reg2.r.tx_master) {
742
		/*Configures BCLK rate*/
743
		div = PLL_OUT_HZ_48;
744
		mod = do_div(div, bclk_rate);
745
		if (mod) {
746
			dev_err(dev, "Unsupported BCLK %dHz\n", bclk_rate);
747
			return -EINVAL;
748
		}
749
		dev_dbg(dev, "enables BCLK %dHz output\n", bclk_rate);
750
		reg5.r.i2s_pcm_clk_div = (u32)div - 1;
751
		reg5.r.i2s_pcm_clk_div_chan_en = 1;
752
	}
753
754
	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL1, reg1.ulval);
755
	regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL2, 0xffffffc0,
756
			   reg2.ulval);
757
	regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL3, 0xffffffc0,
758
			   reg3.ulval);
759
	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL4, reg4.ulval);
760
	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL6, reg6.ulval);
761
	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL5, reg5.ulval);
762
763
	regmap_write(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2,
764
		     regdbt2.ulval);
765
766
	return 0;
767
}
768
769
static void cx2072x_update_eq_coeff(struct snd_soc_component *component)
770
{
771
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
772
	int band, ch, value;
773
774
	if (!cx2072x->plbk_eq_changed)
775
		return;
776
	if (!cx2072x->plbk_eq_en)
777
		return;
778
779
	/* set EQ to bypass mode before configuring the EQ settings */
780
	regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS, 0x620f);
781
782
	for (ch = 0; ch < 2; ch++)
783
		for (band = 0; band < CX2072X_PLBK_EQ_BAND_NUM; band++) {
784
			cx2072x_reg_bulk_write(component, CX2072X_EQ_B0_COEFF,
785
					       &cx2072x->plbk_eq[ch][band][0],
786
					       MAX_EQ_COEFF);
787
			value = band + (ch << 3) + (1 << 6);
788
			regmap_write(cx2072x->regmap, CX2072X_EQ_BAND, value);
789
			mdelay(5);
790
		}
791
792
	cx2072x->plbk_eq_changed = false;
793
	cx2072x->plbk_eq_en_changed = true;
794
}
795
796
static void cx2072x_update_eq_en(struct snd_soc_component *component)
797
{
798
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
799
800
	if (cx2072x->plbk_eq_en_changed) {
801
		if (cx2072x->plbk_eq_en)
802
			regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS,
803
				     0x6203);
804
		else
805
			regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS,
806
				     0x620c);
807
808
		cx2072x->plbk_eq_en_changed = false;
809
	}
810
}
811
812
static void cx2072x_update_drc(struct snd_soc_component *component)
813
{
814
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
815
816
	if (cx2072x->plbk_drc_changed && cx2072x->plbk_drc_en) {
817
		cx2072x_reg_bulk_write(component, CX2072X_SPKR_DRC_ENABLE_STEP,
818
				       cx2072x->plbk_drc, MAX_DRC_REGS);
819
		cx2072x->plbk_drc_changed = false;
820
		cx2072x->plbk_drc_en_changed = true;
821
	}
822
}
823
824
static void cx2072x_update_drc_en(struct snd_soc_component *component)
825
{
826
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
827
	u8 drc_status = cx2072x->plbk_drc[0];
828
829
	if (!cx2072x->plbk_drc_en_changed)
830
		return;
831
832
	if (cx2072x->plbk_drc_en) {
833
		drc_status |= 0x1;
834
		regmap_write(cx2072x->regmap, CX2072X_SPKR_DRC_ENABLE_STEP,
835
			     drc_status);
836
		cx2072x->plbk_drc[0] = drc_status;
837
	} else {
838
		drc_status &= 0xfe;
839
		regmap_write(cx2072x->regmap, CX2072X_SPKR_DRC_ENABLE_STEP,
840
			     drc_status);
841
		cx2072x->plbk_drc[0] = drc_status;
842
	}
843
844
	cx2072x->plbk_drc_en_changed = false;
845
}
846
847
static void cx2072x_update_dsp(struct snd_soc_component *component)
848
{
849
	unsigned int afg_reg;
850
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
851
852
	regmap_read(cx2072x->regmap, CX2072X_AFG_POWER_STATE, &afg_reg);
853
854
	if ((afg_reg & 0xf) != 0)
855
		/*skip since device is on D3 mode*/
856
		return;
857
858
	regmap_read(cx2072x->regmap, CX2072X_PORTG_POWER_STATE, &afg_reg);
859
860
	if ((afg_reg & 0xf) != 0) {
861
		dev_dbg(component->dev, "failed to update dsp dueo portg is off\n");
862
		/*skip since device is on D3 mode*/
863
		return;
864
	}
865
866
	cx2072x_update_eq_coeff(component);
867
	cx2072x_update_eq_en(component);
868
	cx2072x_update_drc(component);
869
	cx2072x_update_drc_en(component);
870
}
871
872
static int afg_power_ev(struct snd_soc_dapm_widget *w,
873
			struct snd_kcontrol *kcontrol, int event)
874
{
875
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
876
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
877
878
	switch (event) {
879
	case SND_SOC_DAPM_POST_PMU:
880
		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0,
881
				   0x00, 0x10);
882
		break;
883
884
	case SND_SOC_DAPM_PRE_PMD:
885
		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0,
886
				   0x10, 0x10);
887
		break;
888
	}
889
890
	return 0;
891
}
892
893
static int portg_power_ev(struct snd_soc_dapm_widget *w,
894
			  struct snd_kcontrol *kcontrol, int event)
895
{
896
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
897
898
	switch (event) {
899
	case SND_SOC_DAPM_POST_PMU:
900
		dev_dbg(component->dev, "portg_power_event\n");
901
		cx2072x_update_dsp(component);
902
		break;
903
904
	default:
905
		break;
906
	}
907
908
	return 0;
909
}
910
911
static int cx2072x_plbk_eq_en_info(struct snd_kcontrol *kcontrol,
912
				   struct snd_ctl_elem_info *uinfo)
913
{
914
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
915
	uinfo->count = 1;
916
	uinfo->value.integer.min = 0;
917
	uinfo->value.integer.max = 1;
918
919
	return 0;
920
}
921
922
static int cx2072x_plbk_eq_en_get(struct snd_kcontrol *kcontrol,
923
				  struct snd_ctl_elem_value *ucontrol)
924
{
925
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
926
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
927
928
	ucontrol->value.integer.value[0] = cx2072x->plbk_eq_en;
929
930
	return 0;
931
}
932
933
static int cx2072x_plbk_eq_en_put(struct snd_kcontrol *kcontrol,
934
				  struct snd_ctl_elem_value *ucontrol)
935
{
936
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
937
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
938
	const bool enable = ucontrol->value.integer.value[0];
939
940
	if (ucontrol->value.integer.value[0] > 1)
941
		return -EINVAL;
942
943
	if (cx2072x->plbk_eq_en != enable) {
944
		cx2072x->plbk_eq_en = enable;
945
		cx2072x->plbk_eq_en_changed = true;
946
		cx2072x_update_dsp(component);
947
	}
948
949
	return 0;
950
}
951
952
static int cx2072x_plbk_drc_en_info(struct snd_kcontrol *kcontrol,
953
				    struct snd_ctl_elem_info *uinfo)
954
{
955
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
956
	uinfo->count = 1;
957
	uinfo->value.integer.min = 0;
958
	uinfo->value.integer.max = 1;
959
960
	return 0;
961
}
962
963
static int cx2072x_plbk_drc_en_get(struct snd_kcontrol *kcontrol,
964
				   struct snd_ctl_elem_value *ucontrol)
965
{
966
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
967
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
968
969
	ucontrol->value.integer.value[0] = cx2072x->plbk_drc_en;
970
971
	return 0;
972
}
973
974
static int cx2072x_plbk_drc_en_put(struct snd_kcontrol *kcontrol,
975
				   struct snd_ctl_elem_value *ucontrol)
976
{
977
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
978
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
979
	const bool enable = ucontrol->value.integer.value[0];
980
981
	if (ucontrol->value.integer.value[0] > 1)
982
		return -EINVAL;
983
984
	if (cx2072x->plbk_drc_en != enable) {
985
		cx2072x->plbk_drc_en = enable;
986
		cx2072x->plbk_drc_en_changed = true;
987
		cx2072x_update_dsp(component);
988
	}
989
990
	return 0;
991
}
992
993
static int cx2072x_plbk_eq_info(struct snd_kcontrol *kcontrol,
994
				struct snd_ctl_elem_info *uinfo)
995
{
996
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
997
	uinfo->count = CX2072X_PLBK_EQ_COEF_LEN;
998
999
	return 0;
1000
}
1001
1002
static int cx2072x_plbk_eq_get(struct snd_kcontrol *kcontrol,
1003
			       struct snd_ctl_elem_value *ucontrol)
1004
{
1005
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1006
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1007
	struct CX2072X_EQ_CTRL *eq =
1008
		(struct CX2072X_EQ_CTRL *)kcontrol->private_value;
1009
	u8 *param = ucontrol->value.bytes.data;
1010
	u8 *cache = cx2072x->plbk_eq[eq->ch][eq->band];
1011
1012
	memcpy(param, cache, CX2072X_PLBK_EQ_COEF_LEN);
1013
1014
	return 0;
1015
}
1016
1017
static int cx2072x_plbk_eq_put(struct snd_kcontrol *kcontrol,
1018
			       struct snd_ctl_elem_value *ucontrol)
1019
{
1020
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1021
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1022
	struct CX2072X_EQ_CTRL *eq =
1023
		(struct CX2072X_EQ_CTRL *)kcontrol->private_value;
1024
	u8 *param = ucontrol->value.bytes.data;
1025
	u8 *cache = cx2072x->plbk_eq[eq->ch][eq->band];
1026
1027
	mutex_lock(&cx2072x->eq_coeff_lock);
1028
1029
	/*do nothing if the value is the same*/
1030
	if (memcmp(cache, param, CX2072X_PLBK_EQ_COEF_LEN))
1031
		goto EXIT;
1032
1033
	memcpy(cache, param, CX2072X_PLBK_EQ_COEF_LEN);
1034
1035
	cx2072x->plbk_eq_changed = true;
1036
	cx2072x->plbk_eq_channel = eq->ch;
1037
1038
	cx2072x_update_dsp(component);
1039
EXIT:
1040
	mutex_unlock(&cx2072x->eq_coeff_lock);
1041
	return 0;
1042
}
1043
1044
static int cx2072x_classd_level_info(struct snd_kcontrol *kcontrol,
1045
				     struct snd_ctl_elem_info *uinfo)
1046
{
1047
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1048
	uinfo->count = CX2072X_CLASSD_AMP_LEN;
1049
1050
	return 0;
1051
}
1052
1053
static int cx2072x_classd_level_get(struct snd_kcontrol *kcontrol,
1054
				    struct snd_ctl_elem_value *ucontrol)
1055
{
1056
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1057
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1058
	u8 *param = ucontrol->value.bytes.data;
1059
	u8 *cache = cx2072x->classd_amp;
1060
1061
	memcpy(param, cache, CX2072X_CLASSD_AMP_LEN);
1062
1063
	return 0;
1064
}
1065
1066
static int cx2072x_classd_level_put(struct snd_kcontrol *kcontrol,
1067
				    struct snd_ctl_elem_value *ucontrol)
1068
{
1069
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1070
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1071
	u8 *param = ucontrol->value.bytes.data;
1072
	u8 *cache = cx2072x->classd_amp;
1073
1074
	memcpy(cache, param, CX2072X_CLASSD_AMP_LEN);
1075
1076
	/* Config Power Averaging */
1077
	cx2072x_reg_bulk_write(component, CX2072X_ANALOG_TEST10,
1078
			       &cx2072x->classd_amp[0], 2);
1079
	cx2072x_reg_bulk_write(component, CX2072X_CODEC_TEST20,
1080
			       &cx2072x->classd_amp[2], 2);
1081
	cx2072x_reg_bulk_write(component, CX2072X_CODEC_TEST26,
1082
			       &cx2072x->classd_amp[4], 2);
1083
	return 0;
1084
}
1085
1086
static int cx2072x_plbk_drc_info(struct snd_kcontrol *kcontrol,
1087
				 struct snd_ctl_elem_info *uinfo)
1088
{
1089
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1090
	uinfo->count = CX2072X_PLBK_DRC_PARM_LEN;
1091
1092
	return 0;
1093
}
1094
1095
static int cx2072x_plbk_drc_get(struct snd_kcontrol *kcontrol,
1096
				struct snd_ctl_elem_value *ucontrol)
1097
{
1098
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1099
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1100
	u8 *param = ucontrol->value.bytes.data;
1101
	u8 *cache = cx2072x->plbk_drc;
1102
1103
	memcpy(param, cache, CX2072X_PLBK_DRC_PARM_LEN);
1104
1105
	return 0;
1106
}
1107
1108
static int cx2072x_plbk_drc_put(struct snd_kcontrol *kcontrol,
1109
				struct snd_ctl_elem_value *ucontrol)
1110
{
1111
	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1112
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1113
	u8 *param = ucontrol->value.bytes.data;
1114
	u8 *cache = cx2072x->plbk_drc;
1115
1116
	memcpy(cache, param, CX2072X_PLBK_DRC_PARM_LEN);
1117
1118
	cx2072x->plbk_drc_changed = true;
1119
	cx2072x_update_dsp(component);
1120
1121
	return 0;
1122
}
1123
1124
#define CX2072X_PLBK_DRC_COEF(xname) \
1125
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1126
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1127
	.info = cx2072x_plbk_drc_info, \
1128
	.get = cx2072x_plbk_drc_get, .put = cx2072x_plbk_drc_put}
1129
1130
#define CX2072X_PLBK_EQ_COEF(xname, xch, xband) \
1131
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1132
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1133
		  SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
1134
	.info = cx2072x_plbk_eq_info, \
1135
	.get = cx2072x_plbk_eq_get, .put = cx2072x_plbk_eq_put, \
1136
	.private_value = \
1137
		(unsigned long)&(struct CX2072X_EQ_CTRL) \
1138
		 {.ch = xch, .band = xband } }
1139
1140
#define CX2072X_PLBK_DSP_EQ_SWITCH(xname) \
1141
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
1142
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1143
	.info = cx2072x_plbk_eq_en_info, \
1144
	.get = cx2072x_plbk_eq_en_get, .put = cx2072x_plbk_eq_en_put}
1145
1146
#define CX2072X_PLBK_DSP_DRC_SWITCH(xname) \
1147
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
1148
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1149
	.info = cx2072x_plbk_drc_en_info, \
1150
	.get = cx2072x_plbk_drc_en_get, .put = cx2072x_plbk_drc_en_put}
1151
1152
#define CX2072X_CLASSD_LEVEL(xname) \
1153
{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
1154
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1155
	.info = cx2072x_classd_level_info, \
1156
	.get = cx2072x_classd_level_get, .put = cx2072x_classd_level_put}
1157
1158
static const struct snd_kcontrol_new cx2072x_snd_controls[] = {
1159
	SOC_DOUBLE_R_TLV("PortD Boost Volume", CX2072X_PORTD_GAIN_LEFT,
1160
			 CX2072X_PORTD_GAIN_RIGHT, 0, 3, 0, boost_tlv),
1161
	SOC_DOUBLE_R_TLV("PortC Boost Volume", CX2072X_PORTC_GAIN_LEFT,
1162
			 CX2072X_PORTC_GAIN_RIGHT, 0, 3, 0, boost_tlv),
1163
	SOC_DOUBLE_R_TLV("PortB Boost Volume", CX2072X_PORTB_GAIN_LEFT,
1164
			 CX2072X_PORTB_GAIN_RIGHT, 0, 3, 0, boost_tlv),
1165
	SOC_DOUBLE_R_TLV("PortD ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_1,
1166
			 CX2072X_ADC1_AMP_GAIN_RIGHT_1, 0, 0x4a, 0, adc_tlv),
1167
	SOC_DOUBLE_R_TLV("PortC ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_2,
1168
			 CX2072X_ADC1_AMP_GAIN_RIGHT_2, 0, 0x4a, 0, adc_tlv),
1169
	SOC_DOUBLE_R_TLV("PortB ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_0,
1170
			 CX2072X_ADC1_AMP_GAIN_RIGHT_0, 0, 0x4a, 0, adc_tlv),
1171
	SOC_DOUBLE_R_TLV("DAC1 Volume", CX2072X_DAC1_AMP_GAIN_LEFT,
1172
			 CX2072X_DAC1_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv),
1173
	SOC_DOUBLE_R("DAC1 Mute Switch", CX2072X_DAC1_AMP_GAIN_LEFT,
1174
		     CX2072X_DAC1_AMP_GAIN_RIGHT, 7,  1, 0),
1175
	SOC_DOUBLE_R_TLV("DAC2 Volume", CX2072X_DAC2_AMP_GAIN_LEFT,
1176
			 CX2072X_DAC2_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv),
1177
	CX2072X_PLBK_DSP_EQ_SWITCH("EQ Switch"),
1178
	CX2072X_PLBK_DSP_DRC_SWITCH("DRC Switch"),
1179
1180
	CX2072X_PLBK_EQ_COEF("DACL EQ 0", 0, 0),
1181
	CX2072X_PLBK_EQ_COEF("DACL EQ 1", 0, 1),
1182
	CX2072X_PLBK_EQ_COEF("DACL EQ 2", 0, 2),
1183
	CX2072X_PLBK_EQ_COEF("DACL EQ 3", 0, 3),
1184
	CX2072X_PLBK_EQ_COEF("DACL EQ 4", 0, 4),
1185
	CX2072X_PLBK_EQ_COEF("DACL EQ 5", 0, 5),
1186
	CX2072X_PLBK_EQ_COEF("DACL EQ 6", 0, 6),
1187
	CX2072X_PLBK_EQ_COEF("DACR EQ 0", 1, 0),
1188
	CX2072X_PLBK_EQ_COEF("DACR EQ 1", 1, 1),
1189
	CX2072X_PLBK_EQ_COEF("DACR EQ 2", 1, 2),
1190
	CX2072X_PLBK_EQ_COEF("DACR EQ 3", 1, 3),
1191
	CX2072X_PLBK_EQ_COEF("DACR EQ 4", 1, 4),
1192
	CX2072X_PLBK_EQ_COEF("DACR EQ 5", 1, 5),
1193
	CX2072X_PLBK_EQ_COEF("DACR EQ 6", 1, 6),
1194
	CX2072X_PLBK_DRC_COEF("DRC"),
1195
	SOC_SINGLE_TLV("HPF Freq", CX2072X_CODEC_TEST9, 0, 0x3f, 0, hpf_tlv),
1196
	SOC_DOUBLE("HPF Switch", CX2072X_CODEC_TEST9, 8, 9, 1, 1),
1197
	CX2072X_CLASSD_LEVEL("Class-D Output Level"),
1198
	SOC_SINGLE("PortA HP Amp Switch", CX2072X_PORTA_PIN_CTRL, 7, 1, 0),
1199
};
1200
1201
/**
1202
 * cx2072x_enable_detect - Enable CX2072X jack detection
1203
 * @component : pointer variable to component having information related to codec
1204
 *
1205
 */
1206
int cx2072x_enable_detect(struct snd_soc_component *component)
1207
{
1208
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1209
	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1210
1211
	/*No-sticky input type*/
1212
	regmap_write(cx2072x->regmap, CX2072X_GPIO_STICKY_MASK, 0x1f);
1213
1214
	/*Use GPOI0 as interrupt pin*/
1215
	regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24);
1216
1217
	/* Enables unsolitited message on PortA*/
1218
	regmap_write(cx2072x->regmap, CX2072X_PORTA_UNSOLICITED_RESPONSE, 0x80);
1219
1220
	/* support both nokia and apple headset set. Monitor time = 275 ms*/
1221
	regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST15, 0x73);
1222
1223
	/* Disable TIP detection*/
1224
	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST12, 0x300);
1225
1226
	/* Switch MusicD3Live pin to GPIO */
1227
	regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST1, 0);
1228
1229
	snd_soc_dapm_mutex_lock(dapm);
1230
1231
	snd_soc_dapm_force_enable_pin_unlocked(dapm, "PORTD");
1232
	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Headset Bias");
1233
	snd_soc_dapm_force_enable_pin_unlocked(dapm, "PortD Mic Bias");
1234
1235
	snd_soc_dapm_mutex_unlock(dapm);
1236
	return 0;
1237
}
1238
EXPORT_SYMBOL_GPL(cx2072x_enable_detect);
1239
1240
/*
1241
 * cx2072x_get_jack_state: Return current jack state.
1242
 * @component : pointer variable to component having information related to codec
1243
 *
1244
 */
1245
int cx2072x_get_jack_state(struct snd_soc_component *component)
1246
{
1247
	unsigned int jack;
1248
	unsigned int type = 0;
1249
	int  state = 0;
1250
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1251
	bool need_cache_bypass =
1252
		snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF;
1253
1254
	if (need_cache_bypass)
1255
		regcache_cache_only(cx2072x->regmap, false);
1256
	cx2072x->jack_state = CX_JACK_NONE;
1257
	regmap_read(cx2072x->regmap, CX2072X_PORTA_PIN_SENSE, &jack);
1258
	jack = jack >> 24;
1259
	regmap_read(cx2072x->regmap, CX2072X_DIGITAL_TEST11, &type);
1260
	if (need_cache_bypass)
1261
		regcache_cache_only(cx2072x->regmap, true);
1262
	if (jack == 0x80) {
1263
		type = type >> 8;
1264
1265
		if (type & 0x8) {
1266
			state |= SND_JACK_HEADSET;
1267
			cx2072x->jack_state = CX_JACK_APPLE_HEADSET;
1268
			if (type & 0x2)
1269
				state |= SND_JACK_BTN_0;
1270
		} else if (type & 0x4) {
1271
			state |= SND_JACK_HEADPHONE;
1272
			cx2072x->jack_state = CX_JACK_NOKIE_HEADSET;
1273
		} else {
1274
			state |= SND_JACK_HEADPHONE;
1275
			cx2072x->jack_state = CX_JACK_HEADPHONE;
1276
		}
1277
	}
1278
1279
	/* clear interrupt */
1280
	regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24);
1281
1282
	dev_dbg(component->dev, "CX2072X_HSDETECT type=0x%X,Jack state = %x\n",
1283
		type, state);
1284
	return state;
1285
}
1286
EXPORT_SYMBOL_GPL(cx2072x_get_jack_state);
1287
1288
static int cx2072x_hw_params(struct snd_pcm_substream *substream,
1289
			     struct snd_pcm_hw_params *params,
1290
			     struct snd_soc_dai *dai)
1291
{
1292
	struct snd_soc_component *component = dai->component;
1293
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1294
	struct device *dev = component->dev;
1295
	const unsigned int sample_rate = params_rate(params);
1296
	int sample_size, frame_size;
1297
1298
	/* Data sizes if not using TDM */
1299
	sample_size = params_width(params);
1300
1301
	if (sample_size < 0)
1302
		return sample_size;
1303
1304
	frame_size = snd_soc_params_to_frame_size(params);
1305
	if (frame_size < 0)
1306
		return frame_size;
1307
1308
	if (cx2072x->mclk_rate == 0) {
1309
		dev_err(dev, "Master clock rate is not configued\n");
1310
		return -EINVAL;
1311
	}
1312
1313
	if (cx2072x->bclk_ratio)
1314
		frame_size = cx2072x->bclk_ratio;
1315
1316
	switch (sample_rate) {
1317
	case 48000:
1318
	case 32000:
1319
	case 24000:
1320
	case 16000:
1321
	case 96000:
1322
	case 192000:
1323
		break;
1324
1325
	default:
1326
		dev_err(dev, "Unsupported sample rate %d\n", sample_rate);
1327
		return -EINVAL;
1328
	}
1329
1330
	dev_dbg(dev, "Sample size %d bits, frame = %d bits, rate = %d Hz\n",
1331
		sample_size, frame_size, sample_rate);
1332
1333
	cx2072x->frame_size = frame_size;
1334
	cx2072x->sample_size = sample_size;
1335
	cx2072x->sample_rate = sample_rate;
1336
1337
	if (dai->id == CX2072X_DAI_DSP) {
1338
		cx2072x->en_aec_ref = true;
1339
		dev_dbg(cx2072x->dev, "enables aec reference\n");
1340
		regmap_write(cx2072x->regmap,
1341
			     CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 3);
1342
	}
1343
1344
	if (cx2072x->pll_changed) {
1345
		cx2072x_config_pll(cx2072x);
1346
		cx2072x->pll_changed = false;
1347
	}
1348
1349
	if (cx2072x->i2spcm_changed) {
1350
		cx2072x_config_i2spcm(cx2072x);
1351
		cx2072x->i2spcm_changed = false;
1352
	}
1353
1354
	return 0;
1355
}
1356
1357
static void cx2072x_shutdown(struct snd_pcm_substream *substream,
1358
			     struct snd_soc_dai *dai)
1359
{
1360
	struct snd_soc_component *component = dai->component;
1361
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1362
1363
	/* shutdown component. */
1364
	regcache_cache_only(cx2072x->regmap, false);
1365
	regmap_write(cx2072x->regmap, CX2072X_PORTA_POWER_STATE, 3);
1366
	regmap_write(cx2072x->regmap, CX2072X_PORTB_POWER_STATE, 3);
1367
	regmap_write(cx2072x->regmap, CX2072X_PORTC_POWER_STATE, 3);
1368
	regmap_write(cx2072x->regmap, CX2072X_PORTD_POWER_STATE, 3);
1369
	regmap_write(cx2072x->regmap, CX2072X_PORTE_POWER_STATE, 3);
1370
	regmap_write(cx2072x->regmap, CX2072X_PORTG_POWER_STATE, 3);
1371
	regmap_write(cx2072x->regmap, CX2072X_MIXER_POWER_STATE, 3);
1372
	regmap_write(cx2072x->regmap, CX2072X_ADC1_POWER_STATE, 3);
1373
	regmap_write(cx2072x->regmap, CX2072X_ADC2_POWER_STATE, 3);
1374
	regmap_write(cx2072x->regmap, CX2072X_DAC1_POWER_STATE, 3);
1375
	regmap_write(cx2072x->regmap, CX2072X_DAC2_POWER_STATE, 3);
1376
1377
	snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
1378
}
1379
1380
static int cx2072x_set_dai_bclk_ratio(struct snd_soc_dai *dai,
1381
				      unsigned int ratio)
1382
{
1383
	struct snd_soc_component *component = dai->component;
1384
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1385
1386
	cx2072x->bclk_ratio = ratio;
1387
1388
	return 0;
1389
}
1390
1391
static int cx2072x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
1392
				  unsigned int freq, int dir)
1393
{
1394
	struct snd_soc_component *component = dai->component;
1395
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1396
1397
	if (cx2072x->mclk && clk_set_rate(cx2072x->mclk, freq)) {
1398
		dev_err(component->dev, "set clk rate failed\n");
1399
		return -EINVAL;
1400
	}
1401
1402
	cx2072x->mclk_rate = freq;
1403
1404
	return 0;
1405
}
1406
1407
static int cx2072x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1408
{
1409
	struct snd_soc_component *component = dai->component;
1410
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1411
	struct device *dev = component->dev;
1412
1413
	dev_dbg(dev, "set_dai_fmt- %08x\n", fmt);
1414
	/* set master/slave */
1415
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1416
	case SND_SOC_DAIFMT_CBM_CFM:
1417
	case SND_SOC_DAIFMT_CBS_CFS:
1418
		break;
1419
1420
	default:
1421
		dev_err(dev, "Unsupported DAI master mode\n");
1422
		return -EINVAL;
1423
	}
1424
1425
	/* set format */
1426
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1427
	case SND_SOC_DAIFMT_I2S:
1428
	case SND_SOC_DAIFMT_RIGHT_J:
1429
	case SND_SOC_DAIFMT_LEFT_J:
1430
		break;
1431
1432
	default:
1433
		dev_err(dev, "Unsupported DAI format\n");
1434
		return -EINVAL;
1435
	}
1436
1437
	/* clock inversion */
1438
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1439
	case SND_SOC_DAIFMT_NB_NF:
1440
	case SND_SOC_DAIFMT_IB_IF:
1441
	case SND_SOC_DAIFMT_IB_NF:
1442
	case SND_SOC_DAIFMT_NB_IF:
1443
		break;
1444
1445
	default:
1446
		dev_err(dev, "Unsupported DAI clock inversion\n");
1447
		return -EINVAL;
1448
	}
1449
1450
	cx2072x->dai_fmt = fmt;
1451
	return 0;
1452
}
1453
1454
static const struct snd_kcontrol_new portaouten_ctl =
1455
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTA_PIN_CTRL, 6, 1, 0);
1456
1457
static const struct snd_kcontrol_new porteouten_ctl =
1458
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL, 6, 1, 0);
1459
1460
static const struct snd_kcontrol_new portgouten_ctl =
1461
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTG_PIN_CTRL, 6, 1, 0);
1462
1463
static const struct snd_kcontrol_new portmouten_ctl =
1464
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTM_PIN_CTRL, 6, 1, 0);
1465
1466
static const struct snd_kcontrol_new portbinen_ctl =
1467
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTB_PIN_CTRL, 5, 1, 0);
1468
1469
static const struct snd_kcontrol_new portcinen_ctl =
1470
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTC_PIN_CTRL, 5, 1, 0);
1471
1472
static const struct snd_kcontrol_new portdinen_ctl =
1473
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTD_PIN_CTRL, 5, 1, 0);
1474
1475
static const struct snd_kcontrol_new porteinen_ctl =
1476
	SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL, 5, 1, 0);
1477
1478
static const struct snd_kcontrol_new i2sadc1l_ctl =
1479
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 0, 1, 0);
1480
1481
static const struct snd_kcontrol_new i2sadc1r_ctl =
1482
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 1, 1, 0);
1483
1484
static const struct snd_kcontrol_new i2sadc2l_ctl =
1485
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 2, 1, 0);
1486
1487
static const struct snd_kcontrol_new i2sadc2r_ctl =
1488
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2, 3, 1, 0);
1489
1490
static const struct snd_kcontrol_new i2sdac1l_ctl =
1491
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 0, 1, 0);
1492
1493
static const struct snd_kcontrol_new i2sdac1r_ctl =
1494
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 1, 1, 0);
1495
1496
static const struct snd_kcontrol_new i2sdac2l_ctl =
1497
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 2, 1, 0);
1498
1499
static const struct snd_kcontrol_new i2sdac2r_ctl =
1500
	SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3, 3, 1, 0);
1501
1502
static const char * const dac_enum_text[] = {
1503
	"DAC1 Switch", "DAC2 Switch",
1504
};
1505
1506
static const struct soc_enum porta_dac_enum =
1507
SOC_ENUM_SINGLE(CX2072X_PORTA_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
1508
1509
static const struct snd_kcontrol_new porta_mux =
1510
SOC_DAPM_ENUM("PortA Mux", porta_dac_enum);
1511
1512
static const struct soc_enum portg_dac_enum =
1513
SOC_ENUM_SINGLE(CX2072X_PORTG_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
1514
1515
static const struct snd_kcontrol_new portg_mux =
1516
SOC_DAPM_ENUM("PortG Mux", portg_dac_enum);
1517
1518
static const struct soc_enum porte_dac_enum =
1519
SOC_ENUM_SINGLE(CX2072X_PORTE_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
1520
1521
static const struct snd_kcontrol_new porte_mux =
1522
SOC_DAPM_ENUM("PortE Mux", porte_dac_enum);
1523
1524
static const struct soc_enum portm_dac_enum =
1525
SOC_ENUM_SINGLE(CX2072X_PORTM_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
1526
1527
static const struct snd_kcontrol_new portm_mux =
1528
SOC_DAPM_ENUM("PortM Mux", portm_dac_enum);
1529
1530
static const char * const adc1in_sel_text[] = {
1531
	"PortB Switch", "PortD Switch", "PortC Switch", "Widget15 Switch",
1532
	"PortE Switch", "PortF Switch", "PortH Switch"
1533
};
1534
1535
static const struct soc_enum adc1in_sel_enum =
1536
SOC_ENUM_SINGLE(CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 0, 7, adc1in_sel_text);
1537
1538
static const struct snd_kcontrol_new adc1_mux =
1539
SOC_DAPM_ENUM("ADC1 Mux", adc1in_sel_enum);
1540
1541
static const char * const adc2in_sel_text[] = {
1542
	"PortC Switch", "Widget15 Switch", "PortH Switch"
1543
};
1544
1545
static const struct soc_enum adc2in_sel_enum =
1546
SOC_ENUM_SINGLE(CX2072X_ADC2_CONNECTION_SELECT_CONTROL, 0, 3, adc2in_sel_text);
1547
1548
static const struct snd_kcontrol_new adc2_mux =
1549
SOC_DAPM_ENUM("ADC2 Mux", adc2in_sel_enum);
1550
1551
static const struct snd_kcontrol_new wid15_mix[] = {
1552
	SOC_DAPM_SINGLE("DAC1L Switch", CX2072X_MIXER_GAIN_LEFT_0, 7, 1, 1),
1553
	SOC_DAPM_SINGLE("DAC1R Switch", CX2072X_MIXER_GAIN_RIGHT_0, 7, 1, 1),
1554
	SOC_DAPM_SINGLE("DAC2L Switch", CX2072X_MIXER_GAIN_LEFT_1, 7, 1, 1),
1555
	SOC_DAPM_SINGLE("DAC2R Switch", CX2072X_MIXER_GAIN_RIGHT_1, 7, 1, 1),
1556
};
1557
1558
#define CX2072X_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, wmask,  won_val, \
1559
	woff_val, wevent, wflags) \
1560
	{.id = snd_soc_dapm_supply, .name = wname, .kcontrol_news = NULL, \
1561
	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1562
	.on_val = won_val, .off_val = woff_val, \
1563
	.subseq = wsubseq, .event = wevent, .event_flags = wflags}
1564
1565
#define CX2072X_DAPM_SWITCH(wname,  wreg, wshift, wmask,  won_val, woff_val, \
1566
	wevent, wflags) \
1567
	{.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
1568
	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1569
	.on_val = won_val, .off_val = woff_val, \
1570
	.event = wevent, .event_flags = wflags}
1571
1572
#define CX2072X_DAPM_SWITCH(wname,  wreg, wshift, wmask,  won_val, woff_val, \
1573
	wevent, wflags) \
1574
	{.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
1575
	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1576
	.on_val = won_val, .off_val = woff_val, \
1577
	.event = wevent, .event_flags = wflags}
1578
1579
#define CX2072X_DAPM_REG_E(wid, wname, wreg, wshift, wmask, won_val, woff_val, \
1580
				wevent, wflags) \
1581
	{.id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
1582
	.reg = wreg, .shift = wshift, .mask = wmask, \
1583
	.on_val = won_val, .off_val = woff_val, \
1584
	.event = wevent, .event_flags = wflags}
1585
1586
static const struct snd_soc_dapm_widget cx2072x_dapm_widgets[] = {
1587
	/*Playback*/
1588
	SND_SOC_DAPM_AIF_IN("In AIF", "Playback", 0, SND_SOC_NOPM, 0, 0),
1589
1590
	SND_SOC_DAPM_SWITCH("I2S DAC1L", SND_SOC_NOPM, 0, 0, &i2sdac1l_ctl),
1591
	SND_SOC_DAPM_SWITCH("I2S DAC1R", SND_SOC_NOPM, 0, 0, &i2sdac1r_ctl),
1592
	SND_SOC_DAPM_SWITCH("I2S DAC2L", SND_SOC_NOPM, 0, 0, &i2sdac2l_ctl),
1593
	SND_SOC_DAPM_SWITCH("I2S DAC2R", SND_SOC_NOPM, 0, 0, &i2sdac2r_ctl),
1594
1595
	SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC1", CX2072X_DAC1_POWER_STATE,
1596
			 0, 0xFFF, 0x00, 0x03),
1597
1598
	SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC2", CX2072X_DAC2_POWER_STATE,
1599
			 0, 0xFFF, 0x00, 0x03),
1600
1601
	SND_SOC_DAPM_MUX("PortA Mux", SND_SOC_NOPM, 0, 0, &porta_mux),
1602
	SND_SOC_DAPM_MUX("PortG Mux", SND_SOC_NOPM, 0, 0, &portg_mux),
1603
	SND_SOC_DAPM_MUX("PortE Mux", SND_SOC_NOPM, 0, 0, &porte_mux),
1604
	SND_SOC_DAPM_MUX("PortM Mux", SND_SOC_NOPM, 0, 0, &portm_mux),
1605
1606
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortA Power",
1607
			 CX2072X_PORTA_POWER_STATE, 0, 0XFFF, 0X00, 0X03),
1608
1609
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortM Power",
1610
			 CX2072X_PORTM_POWER_STATE, 0, 0XFFF, 0X00, 0X03),
1611
1612
	CX2072X_DAPM_SUPPLY_S("PortG Power", 1, CX2072X_PORTG_POWER_STATE, 0,
1613
			      0xFF, 0x00, 0x03, portg_power_ev,
1614
			      SND_SOC_DAPM_POST_PMU),
1615
1616
	CX2072X_DAPM_SUPPLY_S("AFG Power", 0, CX2072X_AFG_POWER_STATE,
1617
			      0, 0xFFF, 0x00, 0x03, afg_power_ev,
1618
			      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1619
1620
	SND_SOC_DAPM_SWITCH("PortA Out En", SND_SOC_NOPM, 0, 0,
1621
			    &portaouten_ctl),
1622
	SND_SOC_DAPM_SWITCH("PortE Out En", SND_SOC_NOPM, 0, 0,
1623
			    &porteouten_ctl),
1624
	SND_SOC_DAPM_SWITCH("PortG Out En", SND_SOC_NOPM, 0, 0,
1625
			    &portgouten_ctl),
1626
	SND_SOC_DAPM_SWITCH("PortM Out En", SND_SOC_NOPM, 0, 0,
1627
			    &portmouten_ctl),
1628
1629
	SND_SOC_DAPM_OUTPUT("PORTA"),
1630
	SND_SOC_DAPM_OUTPUT("PORTG"),
1631
	SND_SOC_DAPM_OUTPUT("PORTE"),
1632
	SND_SOC_DAPM_OUTPUT("PORTM"),
1633
	SND_SOC_DAPM_OUTPUT("AEC REF"),
1634
1635
	/*Capture*/
1636
	SND_SOC_DAPM_AIF_OUT("Out AIF", "Capture", 0, SND_SOC_NOPM, 0, 0),
1637
1638
	SND_SOC_DAPM_SWITCH("I2S ADC1L", SND_SOC_NOPM, 0, 0, &i2sadc1l_ctl),
1639
	SND_SOC_DAPM_SWITCH("I2S ADC1R", SND_SOC_NOPM, 0, 0, &i2sadc1r_ctl),
1640
	SND_SOC_DAPM_SWITCH("I2S ADC2L", SND_SOC_NOPM, 0, 0, &i2sadc2l_ctl),
1641
	SND_SOC_DAPM_SWITCH("I2S ADC2R", SND_SOC_NOPM, 0, 0, &i2sadc2r_ctl),
1642
1643
	SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC1", CX2072X_ADC1_POWER_STATE,
1644
			 0, 0xFF, 0x00, 0x03),
1645
	SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2", CX2072X_ADC2_POWER_STATE,
1646
			 0, 0xFF, 0x00, 0x03),
1647
1648
	SND_SOC_DAPM_MUX("ADC1 Mux", SND_SOC_NOPM, 0, 0, &adc1_mux),
1649
	SND_SOC_DAPM_MUX("ADC2 Mux", SND_SOC_NOPM, 0, 0, &adc2_mux),
1650
1651
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortB Power",
1652
			 CX2072X_PORTB_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
1653
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortC Power",
1654
			 CX2072X_PORTC_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
1655
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortD Power",
1656
			 CX2072X_PORTD_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
1657
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "PortE Power",
1658
			 CX2072X_PORTE_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
1659
	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Widget15 Power",
1660
			 CX2072X_MIXER_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
1661
1662
	SND_SOC_DAPM_MIXER("Widget15 Mixer", SND_SOC_NOPM, 0, 0,
1663
			   wid15_mix, ARRAY_SIZE(wid15_mix)),
1664
	SND_SOC_DAPM_SWITCH("PortB In En", SND_SOC_NOPM, 0, 0, &portbinen_ctl),
1665
	SND_SOC_DAPM_SWITCH("PortC In En", SND_SOC_NOPM, 0, 0, &portcinen_ctl),
1666
	SND_SOC_DAPM_SWITCH("PortD In En", SND_SOC_NOPM, 0, 0, &portdinen_ctl),
1667
	SND_SOC_DAPM_SWITCH("PortE In En", SND_SOC_NOPM, 0, 0, &porteinen_ctl),
1668
1669
	SND_SOC_DAPM_MICBIAS("Headset Bias", CX2072X_ANALOG_TEST11, 1, 0),
1670
	SND_SOC_DAPM_MICBIAS("PortB Mic Bias", CX2072X_PORTB_PIN_CTRL, 2, 0),
1671
	SND_SOC_DAPM_MICBIAS("PortD Mic Bias", CX2072X_PORTD_PIN_CTRL, 2, 0),
1672
	SND_SOC_DAPM_MICBIAS("PortE Mic Bias", CX2072X_PORTE_PIN_CTRL, 2, 0),
1673
	SND_SOC_DAPM_INPUT("PORTB"),
1674
	SND_SOC_DAPM_INPUT("PORTC"),
1675
	SND_SOC_DAPM_INPUT("PORTD"),
1676
	SND_SOC_DAPM_INPUT("PORTEIN"),
1677
1678
};
1679
1680
static const struct snd_soc_dapm_route cx2072x_intercon[] = {
1681
	/* Playback */
1682
	{"In AIF", NULL, "AFG Power"},
1683
	{"I2S DAC1L", "Switch", "In AIF"},
1684
	{"I2S DAC1R", "Switch", "In AIF"},
1685
	{"I2S DAC2L", "Switch", "In AIF"},
1686
	{"I2S DAC2R", "Switch", "In AIF"},
1687
	{"DAC1", NULL, "I2S DAC1L"},
1688
	{"DAC1", NULL, "I2S DAC1R"},
1689
	{"DAC2", NULL, "I2S DAC2L"},
1690
	{"DAC2", NULL, "I2S DAC2R"},
1691
	{"PortA Mux", "DAC1 Switch", "DAC1"},
1692
	{"PortA Mux", "DAC2 Switch", "DAC2"},
1693
	{"PortG Mux", "DAC1 Switch", "DAC1"},
1694
	{"PortG Mux", "DAC2 Switch", "DAC2"},
1695
	{"PortE Mux", "DAC1 Switch", "DAC1"},
1696
	{"PortE Mux", "DAC2 Switch", "DAC2"},
1697
	{"PortM Mux", "DAC1 Switch", "DAC1"},
1698
	{"PortM Mux", "DAC2 Switch", "DAC2"},
1699
	{"Widget15 Mixer", "DAC1L Switch", "DAC1"},
1700
	{"Widget15 Mixer", "DAC1R Switch", "DAC2"},
1701
	{"Widget15 Mixer", "DAC2L Switch", "DAC1"},
1702
	{"Widget15 Mixer", "DAC2R Switch", "DAC2"},
1703
	{"Widget15 Mixer", NULL, "Widget15 Power"},
1704
	{"PortA Out En", "Switch", "PortA Mux"},
1705
	{"PortG Out En", "Switch", "PortG Mux"},
1706
	{"PortE Out En", "Switch", "PortE Mux"},
1707
	{"PortM Out En", "Switch", "PortM Mux"},
1708
	{"PortA Mux", NULL, "PortA Power"},
1709
	{"PortG Mux", NULL, "PortG Power"},
1710
	{"PortE Mux", NULL, "PortE Power"},
1711
	{"PortM Mux", NULL, "PortM Power"},
1712
	{"PortA Out En", NULL, "PortA Power"},
1713
	{"PortG Out En", NULL, "PortG Power"},
1714
	{"PortE Out En", NULL, "PortE Power"},
1715
	{"PortM Out En", NULL, "PortM Power"},
1716
	{"PORTA", NULL, "PortA Out En"},
1717
	{"PORTG", NULL, "PortG Out En"},
1718
	{"PORTE", NULL, "PortE Out En"},
1719
	{"PORTM", NULL, "PortM Out En"},
1720
1721
	/* Capture */
1722
	{"PORTD", NULL, "Headset Bias"},
1723
	{"PortB In En", "Switch", "PORTB"},
1724
	{"PortC In En", "Switch", "PORTC"},
1725
	{"PortD In En", "Switch", "PORTD"},
1726
	{"PortE In En", "Switch", "PORTEIN"},
1727
	{"ADC1 Mux", "PortB Switch", "PortB In En"},
1728
	{"ADC1 Mux", "PortC Switch", "PortC In En"},
1729
	{"ADC1 Mux", "PortD Switch", "PortD In En"},
1730
	{"ADC1 Mux", "PortE Switch", "PortE In En"},
1731
	{"ADC1 Mux", "Widget15 Switch", "Widget15 Mixer"},
1732
	{"ADC2 Mux", "PortC Switch", "PortC In En"},
1733
	{"ADC2 Mux", "Widget15 Switch", "Widget15 Mixer"},
1734
	{"ADC1", NULL, "ADC1 Mux"},
1735
	{"ADC2", NULL, "ADC2 Mux"},
1736
	{"I2S ADC1L", "Switch", "ADC1"},
1737
	{"I2S ADC1R", "Switch", "ADC1"},
1738
	{"I2S ADC2L", "Switch", "ADC2"},
1739
	{"I2S ADC2R", "Switch", "ADC2"},
1740
	{"Out AIF", NULL, "I2S ADC1L"},
1741
	{"Out AIF", NULL, "I2S ADC1R"},
1742
	{"Out AIF", NULL, "I2S ADC2L"},
1743
	{"Out AIF", NULL, "I2S ADC2R"},
1744
	{"Out AIF", NULL, "AFG Power"},
1745
	{"AEC REF", NULL, "Out AIF"},
1746
	{"PortB In En", NULL, "PortB Power"},
1747
	{"PortC In En", NULL, "PortC Power"},
1748
	{"PortD In En", NULL, "PortD Power"},
1749
	{"PortE In En", NULL, "PortE Power"},
1750
};
1751
1752
static void cx2072x_sw_reset(struct cx2072x_priv *cx2072x)
1753
{
1754
	regmap_write(cx2072x->regmap, CX2072X_AFG_FUNCTION_RESET, 0x01);
1755
	regmap_write(cx2072x->regmap, CX2072X_AFG_FUNCTION_RESET, 0x01);
1756
}
1757
1758
static int cx2072x_init(struct snd_soc_component *component)
1759
{
1760
	int ch, band;
1761
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1762
1763
	regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 0);
1764
1765
	/* configre PortC as input device */
1766
	regmap_update_bits(cx2072x->regmap, CX2072X_PORTC_PIN_CTRL,
1767
			   0x20, 0x20);
1768
1769
	cx2072x->plbk_eq_changed = true;
1770
	cx2072x->plbk_drc_changed = true;
1771
1772
	/*use flat eq by default */
1773
	for (ch = 0 ; ch < 2 ; ch++)
1774
		for (band = 0; band < CX2072X_PLBK_EQ_BAND_NUM; band++) {
1775
			cx2072x->plbk_eq[ch][band][1] = 64;
1776
			cx2072x->plbk_eq[ch][band][10] = 3;
1777
		}
1778
1779
	regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2,
1780
			   0x84, 0xFF);
1781
1782
	return 0;
1783
}
1784
1785
static int cx2072x_set_bias_level(struct snd_soc_component *component,
1786
				  enum snd_soc_bias_level level)
1787
{
1788
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1789
	const enum snd_soc_bias_level old_level =
1790
		 snd_soc_component_get_bias_level(component);
1791
	int ret;
1792
1793
	switch (level) {
1794
	case SND_SOC_BIAS_ON:
1795
		break;
1796
1797
	case SND_SOC_BIAS_PREPARE:
1798
		break;
1799
1800
	case SND_SOC_BIAS_STANDBY:
1801
		if (old_level == SND_SOC_BIAS_OFF) {
1802
			if (cx2072x->mclk) {
1803
				dev_dbg(cx2072x->dev,
1804
					"Turn on MCLK with rate %d\n",
1805
					cx2072x->mclk_rate);
1806
				ret = clk_prepare_enable(cx2072x->mclk);
1807
				if (ret)
1808
					return ret;
1809
			}
1810
			regcache_cache_only(cx2072x->regmap, false);
1811
			regmap_write(cx2072x->regmap,
1812
				     CX2072X_AFG_POWER_STATE, 0);
1813
			regcache_sync(cx2072x->regmap);
1814
		}
1815
		break;
1816
1817
	case SND_SOC_BIAS_OFF:
1818
		if (old_level != SND_SOC_BIAS_OFF) {
1819
			/*Shutdown component completely*/
1820
			cx2072x_sw_reset(cx2072x);
1821
			regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 3);
1822
			regcache_mark_dirty(cx2072x->regmap);
1823
			regcache_cache_only(cx2072x->regmap, true);
1824
			cx2072x->plbk_eq_changed = true;
1825
			cx2072x->plbk_drc_changed = true;
1826
			if (cx2072x->mclk) {
1827
				/*delayed mclk shutdown for 200ms*/
1828
				mdelay(200);
1829
				clk_disable_unprepare(cx2072x->mclk);
1830
			}
1831
		}
1832
		break;
1833
	}
1834
1835
	return 0;
1836
}
1837
1838
static int cx2072x_probe(struct snd_soc_component *component)
1839
{
1840
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(component);
1841
	int ret = 0;
1842
	unsigned int ven_id;
1843
1844
	cx2072x->component = component;
1845
1846
	regmap_read(cx2072x->regmap, CX2072X_VENDOR_ID, &ven_id);
1847
	regmap_read(cx2072x->regmap, CX2072X_REVISION_ID, &cx2072x->rev_id);
1848
1849
	dev_info(component->dev, "codec version: %08x,%08x\n",
1850
		 ven_id, cx2072x->rev_id);
1851
1852
	/* Check if MCLK is specified, if not the clock is control by machine
1853
	 * driver
1854
	 */
1855
	cx2072x->mclk = devm_clk_get(component->dev, "mclk");
1856
	if (IS_ERR(cx2072x->mclk)) {
1857
		ret = PTR_ERR(cx2072x->mclk);
1858
		if (ret == -ENOENT) {
1859
			if (IS_ERR(cx2072x->mclk)) {
1860
				dev_warn(component->dev, "Assuming static MCLK\n");
1861
				cx2072x->mclk = NULL;
1862
				ret = 0;
1863
			}
1864
		} else {
1865
			dev_err(component->dev, "Failed to get MCLK: %d\n", ret);
1866
			return ret;
1867
		}
1868
	}
1869
1870
	dev_dbg(component->dev, "Initialize codec\n");
1871
1872
	/* enable clock for codec access*/
1873
	if (cx2072x->mclk)
1874
		ret = clk_prepare_enable(cx2072x->mclk);
1875
1876
	cx2072x_init(component);
1877
1878
	ret = regmap_register_patch(cx2072x->regmap, cx2072x_patch,
1879
				    ARRAY_SIZE(cx2072x_patch));
1880
	if (ret)
1881
		return ret;
1882
	regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 3);
1883
	regcache_cache_only(cx2072x->regmap, true);
1884
1885
	/* disable clock */
1886
	if (cx2072x->mclk)
1887
		clk_disable_unprepare(cx2072x->mclk);
1888
1889
	return ret;
1890
}
1891
1892
static void cx2072x_remove(struct snd_soc_component *component)
1893
{
1894
	/*power off device*/
1895
	snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
1896
1897
	return 0;
1898
}
1899
1900
static bool cx2072x_readable_register(struct device *dev, unsigned int reg)
1901
{
1902
	switch (reg) {
1903
	case CX2072X_VENDOR_ID:
1904
	case CX2072X_REVISION_ID:
1905
	case CX2072X_CURRENT_BCLK_FREQUENCY:
1906
	case CX2072X_AFG_POWER_STATE:
1907
	case CX2072X_UM_RESPONSE:
1908
	case CX2072X_GPIO_DATA:
1909
	case CX2072X_GPIO_ENABLE:
1910
	case CX2072X_GPIO_DIRECTION:
1911
	case CX2072X_GPIO_WAKE:
1912
	case CX2072X_GPIO_UM_ENABLE:
1913
	case CX2072X_GPIO_STICKY_MASK:
1914
	case CX2072X_DAC1_CONVERTER_FORMAT:
1915
	case CX2072X_DAC1_AMP_GAIN_RIGHT:
1916
	case CX2072X_DAC1_AMP_GAIN_LEFT:
1917
	case CX2072X_DAC1_POWER_STATE:
1918
	case CX2072X_DAC1_CONVERTER_STREAM_CHANNEL:
1919
	case CX2072X_DAC1_EAPD_ENABLE:
1920
	case CX2072X_DAC2_CONVERTER_FORMAT:
1921
	case CX2072X_DAC2_AMP_GAIN_RIGHT:
1922
	case CX2072X_DAC2_AMP_GAIN_LEFT:
1923
	case CX2072X_DAC2_POWER_STATE:
1924
	case CX2072X_DAC2_CONVERTER_STREAM_CHANNEL:
1925
	case CX2072X_ADC1_CONVERTER_FORMAT:
1926
	case CX2072X_ADC1_AMP_GAIN_RIGHT_0:
1927
	case CX2072X_ADC1_AMP_GAIN_LEFT_0:
1928
	case CX2072X_ADC1_AMP_GAIN_RIGHT_1:
1929
	case CX2072X_ADC1_AMP_GAIN_LEFT_1:
1930
	case CX2072X_ADC1_AMP_GAIN_RIGHT_2:
1931
	case CX2072X_ADC1_AMP_GAIN_LEFT_2:
1932
	case CX2072X_ADC1_AMP_GAIN_RIGHT_3:
1933
	case CX2072X_ADC1_AMP_GAIN_LEFT_3:
1934
	case CX2072X_ADC1_AMP_GAIN_RIGHT_4:
1935
	case CX2072X_ADC1_AMP_GAIN_LEFT_4:
1936
	case CX2072X_ADC1_AMP_GAIN_RIGHT_5:
1937
	case CX2072X_ADC1_AMP_GAIN_LEFT_5:
1938
	case CX2072X_ADC1_AMP_GAIN_RIGHT_6:
1939
	case CX2072X_ADC1_AMP_GAIN_LEFT_6:
1940
	case CX2072X_ADC1_CONNECTION_SELECT_CONTROL:
1941
	case CX2072X_ADC1_POWER_STATE:
1942
	case CX2072X_ADC1_CONVERTER_STREAM_CHANNEL:
1943
	case CX2072X_ADC2_CONVERTER_FORMAT:
1944
	case CX2072X_ADC2_AMP_GAIN_RIGHT_0:
1945
	case CX2072X_ADC2_AMP_GAIN_LEFT_0:
1946
	case CX2072X_ADC2_AMP_GAIN_RIGHT_1:
1947
	case CX2072X_ADC2_AMP_GAIN_LEFT_1:
1948
	case CX2072X_ADC2_AMP_GAIN_RIGHT_2:
1949
	case CX2072X_ADC2_AMP_GAIN_LEFT_2:
1950
	case CX2072X_ADC2_CONNECTION_SELECT_CONTROL:
1951
	case CX2072X_ADC2_POWER_STATE:
1952
	case CX2072X_ADC2_CONVERTER_STREAM_CHANNEL:
1953
	case CX2072X_PORTA_CONNECTION_SELECT_CTRL:
1954
	case CX2072X_PORTA_POWER_STATE:
1955
	case CX2072X_PORTA_PIN_CTRL:
1956
	case CX2072X_PORTA_UNSOLICITED_RESPONSE:
1957
	case CX2072X_PORTA_PIN_SENSE:
1958
	case CX2072X_PORTA_EAPD_BTL:
1959
	case CX2072X_PORTB_POWER_STATE:
1960
	case CX2072X_PORTB_PIN_CTRL:
1961
	case CX2072X_PORTB_UNSOLICITED_RESPONSE:
1962
	case CX2072X_PORTB_PIN_SENSE:
1963
	case CX2072X_PORTB_EAPD_BTL:
1964
	case CX2072X_PORTB_GAIN_RIGHT:
1965
	case CX2072X_PORTB_GAIN_LEFT:
1966
	case CX2072X_PORTC_POWER_STATE:
1967
	case CX2072X_PORTC_PIN_CTRL:
1968
	case CX2072X_PORTC_GAIN_RIGHT:
1969
	case CX2072X_PORTC_GAIN_LEFT:
1970
	case CX2072X_PORTD_POWER_STATE:
1971
	case CX2072X_PORTD_PIN_CTRL:
1972
	case CX2072X_PORTD_UNSOLICITED_RESPONSE:
1973
	case CX2072X_PORTD_PIN_SENSE:
1974
	case CX2072X_PORTD_GAIN_RIGHT:
1975
	case CX2072X_PORTD_GAIN_LEFT:
1976
	case CX2072X_PORTE_CONNECTION_SELECT_CTRL:
1977
	case CX2072X_PORTE_POWER_STATE:
1978
	case CX2072X_PORTE_PIN_CTRL:
1979
	case CX2072X_PORTE_UNSOLICITED_RESPONSE:
1980
	case CX2072X_PORTE_PIN_SENSE:
1981
	case CX2072X_PORTE_EAPD_BTL:
1982
	case CX2072X_PORTE_GAIN_RIGHT:
1983
	case CX2072X_PORTE_GAIN_LEFT:
1984
	case CX2072X_PORTF_POWER_STATE:
1985
	case CX2072X_PORTF_PIN_CTRL:
1986
	case CX2072X_PORTF_UNSOLICITED_RESPONSE:
1987
	case CX2072X_PORTF_PIN_SENSE:
1988
	case CX2072X_PORTF_GAIN_RIGHT:
1989
	case CX2072X_PORTF_GAIN_LEFT:
1990
	case CX2072X_PORTG_POWER_STATE:
1991
	case CX2072X_PORTG_PIN_CTRL:
1992
	case CX2072X_PORTG_CONNECTION_SELECT_CTRL:
1993
	case CX2072X_PORTG_EAPD_BTL:
1994
	case CX2072X_PORTM_POWER_STATE:
1995
	case CX2072X_PORTM_PIN_CTRL:
1996
	case CX2072X_PORTM_CONNECTION_SELECT_CTRL:
1997
	case CX2072X_PORTM_EAPD_BTL:
1998
	case CX2072X_MIXER_POWER_STATE:
1999
	case CX2072X_MIXER_GAIN_RIGHT_0:
2000
	case CX2072X_MIXER_GAIN_LEFT_0:
2001
	case CX2072X_MIXER_GAIN_RIGHT_1:
2002
	case CX2072X_MIXER_GAIN_LEFT_1:
2003
	case CX2072X_EQ_ENABLE_BYPASS:
2004
	case CX2072X_EQ_B0_COEFF:
2005
	case CX2072X_EQ_B1_COEFF:
2006
	case CX2072X_EQ_B2_COEFF:
2007
	case CX2072X_EQ_A1_COEFF:
2008
	case CX2072X_EQ_A2_COEFF:
2009
	case CX2072X_EQ_G_COEFF:
2010
	case CX2072X_SPKR_DRC_ENABLE_STEP:
2011
	case CX2072X_SPKR_DRC_CONTROL:
2012
	case CX2072X_SPKR_DRC_TEST:
2013
	case CX2072X_DIGITAL_BIOS_TEST0:
2014
	case CX2072X_DIGITAL_BIOS_TEST2:
2015
	case CX2072X_I2SPCM_CONTROL1:
2016
	case CX2072X_I2SPCM_CONTROL2:
2017
	case CX2072X_I2SPCM_CONTROL3:
2018
	case CX2072X_I2SPCM_CONTROL4:
2019
	case CX2072X_I2SPCM_CONTROL5:
2020
	case CX2072X_I2SPCM_CONTROL6:
2021
	case CX2072X_UM_INTERRUPT_CRTL_E:
2022
	case CX2072X_CODEC_TEST2:
2023
	case CX2072X_CODEC_TEST9:
2024
	case CX2072X_CODEC_TEST20:
2025
	case CX2072X_CODEC_TEST26:
2026
	case CX2072X_ANALOG_TEST4:
2027
	case CX2072X_ANALOG_TEST5:
2028
	case CX2072X_ANALOG_TEST6:
2029
	case CX2072X_ANALOG_TEST7:
2030
	case CX2072X_ANALOG_TEST8:
2031
	case CX2072X_ANALOG_TEST9:
2032
	case CX2072X_ANALOG_TEST10:
2033
	case CX2072X_ANALOG_TEST11:
2034
	case CX2072X_ANALOG_TEST12:
2035
	case CX2072X_ANALOG_TEST13:
2036
	case CX2072X_DIGITAL_TEST0:
2037
	case CX2072X_DIGITAL_TEST1:
2038
	case CX2072X_DIGITAL_TEST11:
2039
	case CX2072X_DIGITAL_TEST12:
2040
	case CX2072X_DIGITAL_TEST15:
2041
	case CX2072X_DIGITAL_TEST16:
2042
	case CX2072X_DIGITAL_TEST17:
2043
	case CX2072X_DIGITAL_TEST18:
2044
	case CX2072X_DIGITAL_TEST19:
2045
	case CX2072X_DIGITAL_TEST20:
2046
		return true;
2047
	default:
2048
		return false;
2049
	}
2050
}
2051
2052
static bool cx2072x_volatile_register(struct device *dev, unsigned int reg)
2053
{
2054
	switch (reg) {
2055
	case CX2072X_VENDOR_ID:
2056
	case CX2072X_REVISION_ID:
2057
	case CX2072X_UM_INTERRUPT_CRTL_E:
2058
	case CX2072X_DIGITAL_TEST11:
2059
	case CX2072X_PORTA_PIN_SENSE:
2060
	case CX2072X_PORTB_PIN_SENSE:
2061
	case CX2072X_PORTD_PIN_SENSE:
2062
	case CX2072X_PORTE_PIN_SENSE:
2063
	case CX2072X_PORTF_PIN_SENSE:
2064
	case CX2072X_EQ_G_COEFF:
2065
	case CX2072X_EQ_BAND:
2066
		return true;
2067
	default:
2068
		return false;
2069
	}
2070
}
2071
2072
static struct snd_soc_component_driver soc_codec_driver_cx2072x = {
2073
	.probe = cx2072x_probe,
2074
	.remove = cx2072x_remove,
2075
	.set_bias_level = cx2072x_set_bias_level,
2076
	.controls = cx2072x_snd_controls,
2077
	.num_controls = ARRAY_SIZE(cx2072x_snd_controls),
2078
	.dapm_widgets = cx2072x_dapm_widgets,
2079
	.num_dapm_widgets = ARRAY_SIZE(cx2072x_dapm_widgets),
2080
	.dapm_routes = cx2072x_intercon,
2081
	.num_dapm_routes = ARRAY_SIZE(cx2072x_intercon),
2082
};
2083
2084
/*
2085
 * DAI ops
2086
 */
2087
static struct snd_soc_dai_ops cx2072x_dai_ops = {
2088
	.set_sysclk = cx2072x_set_dai_sysclk,
2089
	.set_fmt = cx2072x_set_dai_fmt,
2090
	.hw_params = cx2072x_hw_params,
2091
	.shutdown = cx2072x_shutdown,
2092
	.set_bclk_ratio = cx2072x_set_dai_bclk_ratio,
2093
};
2094
2095
static int cx2072x_dsp_dai_probe(struct snd_soc_dai *dai)
2096
{
2097
	struct cx2072x_priv *cx2072x = snd_soc_component_get_drvdata(dai->component);
2098
2099
	dev_dbg(cx2072x->dev, "dsp_dai_probe()\n");
2100
2101
	cx2072x->en_aec_ref = true;
2102
2103
	return 0;
2104
}
2105
2106
#define CX2072X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
2107
			 | SNDRV_PCM_FMTBIT_S24_LE)
2108
2109
static struct snd_soc_dai_driver soc_component_cx2072x_dai[] = {
2110
	{ /* playback and capture */
2111
		.name = "cx2072x-hifi",
2112
		.id	= CX2072X_DAI_HIFI,
2113
		.playback = {
2114
			.stream_name = "Playback",
2115
			.channels_min = 1,
2116
			.channels_max = 2,
2117
			.rates = CX2072X_RATES_DSP,
2118
			.formats = CX2072X_FORMATS,
2119
		},
2120
		.capture = {
2121
			.stream_name = "Capture",
2122
			.channels_min = 1,
2123
			.channels_max = 2,
2124
			.rates = CX2072X_RATES_DSP,
2125
			.formats = CX2072X_FORMATS,
2126
		},
2127
		.ops = &cx2072x_dai_ops,
2128
		.symmetric_rates = 1,
2129
	},
2130
	{ /* plabayck only, return echo reference to Conexant DSP chip*/
2131
		.name = "cx2072x-dsp",
2132
		.id	= CX2072X_DAI_DSP,
2133
		.probe = cx2072x_dsp_dai_probe,
2134
		.playback = {
2135
			.stream_name = "Playback",
2136
			.channels_min = 2,
2137
			.channels_max = 2,
2138
			.rates = CX2072X_RATES_DSP,
2139
			.formats = CX2072X_FORMATS,
2140
		},
2141
		.ops = &cx2072x_dai_ops,
2142
	},
2143
	{ /* plabayck only, return echo reference through I2S TX*/
2144
		.name = "cx2072x-aec",
2145
		.id	= 3,
2146
		.capture = {
2147
			.stream_name = "Capture",
2148
			.channels_min = 2,
2149
			.channels_max = 2,
2150
			.rates = CX2072X_RATES_DSP,
2151
			.formats = CX2072X_FORMATS,
2152
		},
2153
	},
2154
};
2155
EXPORT_SYMBOL_GPL(soc_component_cx2072x_dai);
2156
2157
static const struct regmap_config cx2072x_regmap = {
2158
	.reg_bits = 16,
2159
	.val_bits = 32,
2160
	.max_register = CX2072X_REG_MAX, .reg_defaults = cx2072x_reg_defaults,
2161
	.num_reg_defaults = ARRAY_SIZE(cx2072x_reg_defaults),
2162
	.cache_type = REGCACHE_RBTREE,
2163
	.readable_reg = cx2072x_readable_register,
2164
	.volatile_reg = cx2072x_volatile_register,
2165
	/* Needs custom READ/WRITE functions
2166
	 * for various register lengths.
2167
	 */
2168
	.reg_read = cx2072x_reg_read,
2169
	.reg_write = cx2072x_reg_write,
2170
};
2171
2172
static int cx2072x_i2c_probe(struct i2c_client *i2c,
2173
			     const struct i2c_device_id *id)
2174
{
2175
	int ret = -1;
2176
	struct cx2072x_priv *cx2072x;
2177
2178
	cx2072x = devm_kzalloc(&i2c->dev, sizeof(struct cx2072x_priv),
2179
			       GFP_KERNEL);
2180
	if (!cx2072x)
2181
		return -ENOMEM;
2182
2183
	cx2072x->regmap = devm_regmap_init(&i2c->dev, NULL, i2c,
2184
		&cx2072x_regmap);
2185
2186
	if (IS_ERR(cx2072x->regmap)) {
2187
		ret = PTR_ERR(cx2072x->regmap);
2188
		dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
2189
		return ret;
2190
	}
2191
2192
	mutex_init(&cx2072x->eq_coeff_lock);
2193
2194
	i2c_set_clientdata(i2c, cx2072x);
2195
2196
	cx2072x->dev = &i2c->dev;
2197
	cx2072x->pll_changed = true;
2198
	cx2072x->i2spcm_changed = true;
2199
2200
	/* sets the frame size to
2201
	 * Frame size = number of channel * sample width
2202
	 */
2203
	cx2072x->bclk_ratio = 0;
2204
2205
	ret = snd_soc_register_component(cx2072x->dev, &soc_codec_driver_cx2072x,
2206
				     soc_component_cx2072x_dai,
2207
				     ARRAY_SIZE(soc_component_cx2072x_dai));
2208
	if (ret < 0)
2209
		dev_err(cx2072x->dev,
2210
			"Failed to register codec: %d\n", ret);
2211
	else
2212
		dev_dbg(cx2072x->dev,
2213
			"%s: Register codec.\n", __func__);
2214
2215
	return ret;
2216
}
2217
2218
static int cx2072x_i2c_remove(struct i2c_client *client)
2219
{
2220
	snd_soc_unregister_component(&client->dev);
2221
2222
	return 0;
2223
}
2224
2225
static const struct i2c_device_id cx2072x_i2c_id[] = {
2226
	{ "cx20721", 0 },
2227
	{ "cx20723", 0 },
2228
	{}
2229
};
2230
MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id);
2231
2232
static const struct of_device_id cx2072x_of_match[] = {
2233
	{ .compatible = "cnxt,cx20721", },
2234
	{ .compatible = "cnxt,cx20723", },
2235
	{ .compatible = "cnxt,cx7601", },
2236
	{}
2237
};
2238
MODULE_DEVICE_TABLE(of, cx2072x_of_match);
2239
2240
#ifdef CONFIG_ACPI
2241
static struct acpi_device_id cx2072x_acpi_match[] = {
2242
	{ "14F10720", 0 },
2243
	{},
2244
};
2245
MODULE_DEVICE_TABLE(acpi, cx2072x_acpi_match);
2246
#endif
2247
2248
static struct i2c_driver cx2072x_i2c_driver = {
2249
	.probe = cx2072x_i2c_probe,
2250
	.remove = cx2072x_i2c_remove,
2251
	.id_table = cx2072x_i2c_id,
2252
	.driver = {
2253
		.name = "cx2072x",
2254
		.of_match_table = cx2072x_of_match,
2255
		.acpi_match_table = ACPI_PTR(cx2072x_acpi_match),
2256
	},
2257
};
2258
2259
module_i2c_driver(cx2072x_i2c_driver);
2260
2261
MODULE_DESCRIPTION("ASoC cx2072x Codec Driver");
2262
MODULE_AUTHOR("Simon Ho <simon.ho@conexant.com>");
2263
MODULE_LICENSE("GPL");
(-)linux-4.20/sound/soc/codecs/cx2072x.h (+320 lines)
Line 0 Link Here
1
/*
2
 * ALSA SoC CX20721/CX20723 codec driver
3
 *
4
 * Copyright:	(C) 2017 Conexant Systems, Inc.
5
 * Author:	Simon Ho, <Simon.ho@conexant.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 *
11
 ************************************************************************/
12
#define NUM_OF_DAI 1
13
#define CX2072X_MCLK_PLL 1
14
#define CX2072X_MCLK_EXTERNAL_PLL 1
15
#define CX2072X_MCLK_INTERNAL_OSC 2
16
17
/*#define CX2072X_RATES		SNDRV_PCM_RATE_8000_192000*/
18
#define CX2072X_RATES_DSP	SNDRV_PCM_RATE_48000
19
20
#define CX2072X_REG_MAX 0x8a3c
21
#define AUDDRV_VERSION(major0, major1, minor, build) \
22
		((major0) << 24 | (major1) << 16 | (minor) << 8 | (build))
23
24
#define CX2072X_VENDOR_ID				 0x0200
25
#define CX2072X_REVISION_ID				 0x0208
26
#define CX2072X_CURRENT_BCLK_FREQUENCY			 0x00dc
27
#define CX2072X_AFG_POWER_STATE				 0x0414
28
#define CX2072X_UM_RESPONSE				 0x0420
29
#define CX2072X_GPIO_DATA				 0x0454
30
#define CX2072X_GPIO_ENABLE				 0x0458
31
#define CX2072X_GPIO_DIRECTION				 0x045c
32
#define CX2072X_GPIO_WAKE				 0x0460
33
#define CX2072X_GPIO_UM_ENABLE				 0x0464
34
#define CX2072X_GPIO_STICKY_MASK			 0x0468
35
#define CX2072X_AFG_FUNCTION_RESET			 0x07FC
36
#define CX2072X_DAC1_CONVERTER_FORMAT			 0x43c8
37
#define CX2072X_DAC1_AMP_GAIN_RIGHT			 0x41c0
38
#define CX2072X_DAC1_AMP_GAIN_LEFT			 0x41e0
39
#define CX2072X_DAC1_POWER_STATE			 0x4014
40
#define CX2072X_DAC1_CONVERTER_STREAM_CHANNEL		 0x4018
41
#define CX2072X_DAC1_EAPD_ENABLE			 0x4030
42
#define CX2072X_DAC2_CONVERTER_FORMAT			 0x47c8
43
#define CX2072X_DAC2_AMP_GAIN_RIGHT			 0x45c0
44
#define CX2072X_DAC2_AMP_GAIN_LEFT			 0x45e0
45
#define CX2072X_DAC2_POWER_STATE			 0x4414
46
#define CX2072X_DAC2_CONVERTER_STREAM_CHANNEL		 0x4418
47
#define CX2072X_ADC1_CONVERTER_FORMAT			 0x4fc8
48
#define CX2072X_ADC1_AMP_GAIN_RIGHT_0			 0x4d80
49
#define CX2072X_ADC1_AMP_GAIN_LEFT_0			 0x4da0
50
#define CX2072X_ADC1_AMP_GAIN_RIGHT_1			 0x4d84
51
#define CX2072X_ADC1_AMP_GAIN_LEFT_1			 0x4da4
52
#define CX2072X_ADC1_AMP_GAIN_RIGHT_2			 0x4d88
53
#define CX2072X_ADC1_AMP_GAIN_LEFT_2			 0x4da8
54
#define CX2072X_ADC1_AMP_GAIN_RIGHT_3			 0x4d8c
55
#define CX2072X_ADC1_AMP_GAIN_LEFT_3			 0x4dac
56
#define CX2072X_ADC1_AMP_GAIN_RIGHT_4			 0x4d90
57
#define CX2072X_ADC1_AMP_GAIN_LEFT_4			 0x4db0
58
#define CX2072X_ADC1_AMP_GAIN_RIGHT_5			 0x4d94
59
#define CX2072X_ADC1_AMP_GAIN_LEFT_5			 0x4db4
60
#define CX2072X_ADC1_AMP_GAIN_RIGHT_6			 0x4d98
61
#define CX2072X_ADC1_AMP_GAIN_LEFT_6			 0x4db8
62
#define CX2072X_ADC1_CONNECTION_SELECT_CONTROL		 0x4c04
63
#define CX2072X_ADC1_POWER_STATE			 0x4c14
64
#define CX2072X_ADC1_CONVERTER_STREAM_CHANNEL		 0x4c18
65
#define CX2072X_ADC2_CONVERTER_FORMAT			 0x53c8
66
#define CX2072X_ADC2_AMP_GAIN_RIGHT_0			 0x5180
67
#define CX2072X_ADC2_AMP_GAIN_LEFT_0			 0x51a0
68
#define CX2072X_ADC2_AMP_GAIN_RIGHT_1			 0x5184
69
#define CX2072X_ADC2_AMP_GAIN_LEFT_1			 0x51a4
70
#define CX2072X_ADC2_AMP_GAIN_RIGHT_2			 0x5188
71
#define CX2072X_ADC2_AMP_GAIN_LEFT_2			 0x51a8
72
#define CX2072X_ADC2_CONNECTION_SELECT_CONTROL		 0x5004
73
#define CX2072X_ADC2_POWER_STATE			 0x5014
74
#define CX2072X_ADC2_CONVERTER_STREAM_CHANNEL		 0x5018
75
#define CX2072X_PORTA_CONNECTION_SELECT_CTRL		 0x5804
76
#define CX2072X_PORTA_POWER_STATE			 0x5814
77
#define CX2072X_PORTA_PIN_CTRL				 0x581c
78
#define CX2072X_PORTA_UNSOLICITED_RESPONSE		 0x5820
79
#define CX2072X_PORTA_PIN_SENSE				 0x5824
80
#define CX2072X_PORTA_EAPD_BTL				 0x5830
81
#define CX2072X_PORTB_POWER_STATE			 0x6014
82
#define CX2072X_PORTB_PIN_CTRL				 0x601c
83
#define CX2072X_PORTB_UNSOLICITED_RESPONSE		 0x6020
84
#define CX2072X_PORTB_PIN_SENSE				 0x6024
85
#define CX2072X_PORTB_EAPD_BTL				 0x6030
86
#define CX2072X_PORTB_GAIN_RIGHT			 0x6180
87
#define CX2072X_PORTB_GAIN_LEFT				 0x61a0
88
#define CX2072X_PORTC_POWER_STATE			 0x6814
89
#define CX2072X_PORTC_PIN_CTRL				 0x681c
90
#define CX2072X_PORTC_GAIN_RIGHT			 0x6980
91
#define CX2072X_PORTC_GAIN_LEFT				 0x69a0
92
#define CX2072X_PORTD_POWER_STATE			 0x6414
93
#define CX2072X_PORTD_PIN_CTRL				 0x641c
94
#define CX2072X_PORTD_UNSOLICITED_RESPONSE		 0x6420
95
#define CX2072X_PORTD_PIN_SENSE				 0x6424
96
#define CX2072X_PORTD_GAIN_RIGHT			 0x6580
97
#define CX2072X_PORTD_GAIN_LEFT				 0x65a0
98
#define CX2072X_PORTE_CONNECTION_SELECT_CTRL		 0x7404
99
#define CX2072X_PORTE_POWER_STATE			 0x7414
100
#define CX2072X_PORTE_PIN_CTRL				 0x741c
101
#define CX2072X_PORTE_UNSOLICITED_RESPONSE		 0x7420
102
#define CX2072X_PORTE_PIN_SENSE				 0x7424
103
#define CX2072X_PORTE_EAPD_BTL				 0x7430
104
#define CX2072X_PORTE_GAIN_RIGHT			 0x7580
105
#define CX2072X_PORTE_GAIN_LEFT				 0x75a0
106
#define CX2072X_PORTF_POWER_STATE			 0x7814
107
#define CX2072X_PORTF_PIN_CTRL				 0x781c
108
#define CX2072X_PORTF_UNSOLICITED_RESPONSE		 0x7820
109
#define CX2072X_PORTF_PIN_SENSE				 0x7824
110
#define CX2072X_PORTF_GAIN_RIGHT			 0x7980
111
#define CX2072X_PORTF_GAIN_LEFT				 0x79a0
112
#define CX2072X_PORTG_POWER_STATE			 0x5c14
113
#define CX2072X_PORTG_PIN_CTRL				 0x5c1c
114
#define CX2072X_PORTG_CONNECTION_SELECT_CTRL		 0x5c04
115
#define CX2072X_PORTG_EAPD_BTL				 0x5c30
116
#define CX2072X_PORTM_POWER_STATE			 0x8814
117
#define CX2072X_PORTM_PIN_CTRL				 0x881c
118
#define CX2072X_PORTM_CONNECTION_SELECT_CTRL		 0x8804
119
#define CX2072X_PORTM_EAPD_BTL				 0x8830
120
#define CX2072X_MIXER_POWER_STATE			 0x5414
121
#define CX2072X_MIXER_GAIN_RIGHT_0			 0x5580
122
#define CX2072X_MIXER_GAIN_LEFT_0			 0x55a0
123
#define CX2072X_MIXER_GAIN_RIGHT_1			 0x5584
124
#define CX2072X_MIXER_GAIN_LEFT_1			 0x55a4
125
#define CX2072X_EQ_ENABLE_BYPASS			 0x6d00
126
#define CX2072X_EQ_B0_COEFF				 0x6d02
127
#define CX2072X_EQ_B1_COEFF				 0x6d04
128
#define CX2072X_EQ_B2_COEFF				 0x6d06
129
#define CX2072X_EQ_A1_COEFF				 0x6d08
130
#define CX2072X_EQ_A2_COEFF				 0x6d0a
131
#define CX2072X_EQ_G_COEFF				 0x6d0c
132
#define CX2072X_EQ_BAND					 0x6d0d
133
#define CX2072X_SPKR_DRC_ENABLE_STEP			 0x6d10
134
#define CX2072X_SPKR_DRC_CONTROL			 0x6d14
135
#define CX2072X_SPKR_DRC_TEST				 0X6D18
136
#define CX2072X_DIGITAL_BIOS_TEST0			 0x6d80
137
#define CX2072X_DIGITAL_BIOS_TEST2			 0x6d84
138
#define CX2072X_I2SPCM_CONTROL1				 0x6e00
139
#define CX2072X_I2SPCM_CONTROL2				 0x6e04
140
#define CX2072X_I2SPCM_CONTROL3				 0x6e08
141
#define CX2072X_I2SPCM_CONTROL4				 0x6e0c
142
#define CX2072X_I2SPCM_CONTROL5				 0x6e10
143
#define CX2072X_I2SPCM_CONTROL6				 0x6e18
144
#define CX2072X_UM_INTERRUPT_CRTL_E			 0x6e14
145
#define CX2072X_CODEC_TEST2				 0x7108
146
#define CX2072X_CODEC_TEST9				 0x7124
147
#define CX2072X_CODEC_TEST20				 0x7310
148
#define CX2072X_CODEC_TEST26				 0x7328
149
#define CX2072X_ANALOG_TEST3				 0x718c
150
#define CX2072X_ANALOG_TEST4				 0x7190
151
#define CX2072X_ANALOG_TEST5				 0x7194
152
#define CX2072X_ANALOG_TEST6				 0x7198
153
#define CX2072X_ANALOG_TEST7				 0x719c
154
#define CX2072X_ANALOG_TEST8				 0x71a0
155
#define CX2072X_ANALOG_TEST9				 0x71a4
156
#define CX2072X_ANALOG_TEST10				 0x71a8
157
#define CX2072X_ANALOG_TEST11				 0x71ac
158
#define CX2072X_ANALOG_TEST12				 0x71b0
159
#define CX2072X_ANALOG_TEST13				 0x71b4
160
#define CX2072X_DIGITAL_TEST0				 0x7200
161
#define CX2072X_DIGITAL_TEST1				 0x7204
162
#define CX2072X_DIGITAL_TEST11				 0x722c
163
#define CX2072X_DIGITAL_TEST12				 0x7230
164
#define CX2072X_DIGITAL_TEST15				 0x723c
165
#define CX2072X_DIGITAL_TEST16				 0x7080
166
#define CX2072X_DIGITAL_TEST17				 0x7084
167
#define CX2072X_DIGITAL_TEST18				 0x7088
168
#define CX2072X_DIGITAL_TEST19				 0x708c
169
#define CX2072X_DIGITAL_TEST20				 0x7090
170
171
#define INVALID_GPIO -1
172
#define MAX_EQ_BAND 7
173
#define MAX_EQ_COEFF 11
174
#define MAX_DRC_REGS 9
175
#define MIC_EQ_COEFF 10
176
/* DAI interfae type*/
177
178
#define CX2072X_DAI_HIFI 1
179
#define CX2072X_DAI_DSP  2
180
/*4 ch, including mic and aec*/
181
#define CX2072X_DAI_DSP_PWM 3
182
183
enum cx2072x_jack_types {
184
	CX_JACK_NONE = 0x0000,
185
	CX_JACK_HEADPHONE = 0x0001,
186
	CX_JACK_APPLE_HEADSET = 0x0002,
187
	CX_JACK_NOKIE_HEADSET = 0x0003,
188
};
189
190
int cx2072x_enable_detect(struct snd_soc_component *component);
191
int cx2072x_get_jack_state(struct snd_soc_component *component);
192
193
enum REG_SAMPLE_SIZE {
194
	SAMPLE_SIZE_8_BITS = 0,
195
	SAMPLE_SIZE_16_BITS = 1,
196
	SAMPLE_SIZE_24_BITS = 2,
197
	SAMPLE_SIZE_RESERVED = 3,
198
};
199
200
union REG_I2SPCM_CTRL_REG1 {
201
	struct {
202
		u32 rx_data_one_line:1;
203
		u32 rx_ws_pol:1;
204
		u32 rx_ws_wid:7;
205
		u32 rx_frm_len:5;
206
		u32 rx_sa_size:2;
207
		u32 tx_data_one_line:1;
208
		u32 tx_ws_pol:1;
209
		u32 tx_ws_wid:7;
210
		u32 tx_frm_len:5;
211
		u32 tx_sa_size:2;
212
	} r;
213
	u32 ulval;
214
};
215
216
union REG_I2SPCM_CTRL_REG2 {
217
	struct {
218
		u32 tx_en_ch1:1;
219
		u32 tx_en_ch2:1;
220
		u32 tx_en_ch3:1;
221
		u32 tx_en_ch4:1;
222
		u32 tx_en_ch5:1;
223
		u32 tx_en_ch6:1;
224
		u32 tx_slot_1:5;
225
		u32 tx_slot_2:5;
226
		u32 tx_slot_3:5;
227
		u32 tx_slot_4:5;
228
		u32 res:1;
229
		u32 tx_data_neg_bclk:1;
230
		u32 tx_master:1;
231
		u32 tx_tri_n:1;
232
		u32 tx_endian_sel:1;
233
		u32 tx_dstart_dly:1;
234
	} r;
235
	u32 ulval;
236
};
237
238
union REG_I2SPCM_CTRL_REG3 {
239
	struct {
240
		u32 rx_en_ch1:1;
241
		u32 rx_en_ch2:1;
242
		u32 rx_en_ch3:1;
243
		u32 rx_en_ch4:1;
244
		u32 rx_en_ch5:1;
245
		u32 rx_en_ch6:1;
246
		u32 rx_slot_1:5;
247
		u32 rx_slot_2:5;
248
		u32 rx_slot_3:5;
249
		u32 rx_slot_4:5;
250
		u32 res:1;
251
		u32 rx_data_neg_bclk:1;
252
		u32 rx_master:1;
253
		u32 rx_tri_n:1;
254
		u32 rx_endian_sel:1;
255
		u32 rx_dstart_dly:1;
256
	} r;
257
	u32 ulval;
258
};
259
260
union REG_I2SPCM_CTRL_REG4 {
261
	struct {
262
		u32 rx_mute:1;
263
		u32 tx_mute:1;
264
		u32 reserved:1;
265
		u32 dac_34_independent:1;
266
		u32 dac_bclk_lrck_share:1;
267
		u32 bclk_lrck_share_en:1;
268
		u32 reserved2:2;
269
		u32 rx_last_dac_ch_en:1;
270
		u32 rx_last_dac_ch:3;
271
		u32 tx_last_adc_ch_en:1;
272
		u32 tx_last_adc_ch:3;
273
		u32 rx_slot_5:5;
274
		u32 rx_slot_6:5;
275
		u32 reserved3:6;
276
	} r;
277
	u32 ulval;
278
};
279
280
union REG_I2SPCM_CTRL_REG5 {
281
	struct {
282
		u32 tx_slot_5:5;
283
		u32 reserved:3;
284
		u32 tx_slot_6:5;
285
		u32 reserved2:3;
286
		u32 reserved3:8;
287
		u32 i2s_pcm_clk_div:7;
288
		u32 i2s_pcm_clk_div_chan_en:1;
289
	} r;
290
	u32 ulval;
291
};
292
293
union REG_I2SPCM_CTRL_REG6 {
294
	struct {
295
		u32 reserved:5;
296
		u32 rx_pause_cycles:3;
297
		u32 rx_pause_start_pos:8;
298
		u32 reserved2:5;
299
		u32 tx_pause_cycles:3;
300
		u32 tx_pause_start_pos:8;
301
	} r;
302
	u32 ulval;
303
};
304
305
union REG_DIGITAL_BIOS_TEST2 {
306
	struct {
307
		u32 pull_down_eapd:2;
308
		u32 input_en_eapd_pad:1;
309
		u32 push_pull_mode:1;
310
		u32 eapd_pad_output_driver:2;
311
		u32 pll_source:1;
312
		u32 i2s_bclk_en:1;
313
		u32 i2s_bclk_invert:1;
314
		u32 pll_ref_clock:1;
315
		u32 class_d_shield_clk:1;
316
		u32 audio_pll_bypass_mode:1;
317
		u32 reserved:4;
318
	} r;
319
	u32 ulval;
320
};
(-)linux-4.20/sound/soc/intel/boards/Kconfig (+11 lines)
Lines 92-97 Link Here
92
	  Say Y or m if you have such a device. This is a recommended option.
92
	  Say Y or m if you have such a device. This is a recommended option.
93
	  If unsure select "N".
93
	  If unsure select "N".
94
94
95
config SND_SOC_INTEL_CHT_CX2072X_MACH
96
        tristate "Baytrail and Cherrytrail with CX2072X codec"
97
        depends on X86_INTEL_LPSS && I2C && ACPI
98
	select SND_SOC_ACPI
99
        select SND_SOC_CX2072X
100
        help
101
          This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
102
          platforms with Conexant CX2072X audio codec.
103
          Say Y if you have such a device.
104
          If unsure select "N".
105
95
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
106
config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
96
	tristate "Cherrytrail & Braswell with RT5672 codec"
107
	tristate "Cherrytrail & Braswell with RT5672 codec"
97
	depends on X86_INTEL_LPSS && I2C && ACPI
108
	depends on X86_INTEL_LPSS && I2C && ACPI
(-)linux-4.20/sound/soc/intel/boards/Makefile (+2 lines)
Lines 9-14 Link Here
9
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o
9
snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o
10
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
10
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
11
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
11
snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
12
snd-soc-sst-cht-cx2072x-objs := cht_cx2072x.o
12
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
13
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
13
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
14
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
14
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
15
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
Lines 35-40 Link Here
35
obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
36
obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
36
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
37
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
37
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
38
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
39
obj-$(CONFIG_SND_SOC_INTEL_CHT_CX2072X_MACH) += snd-soc-sst-cht-cx2072x.o
38
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
40
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
39
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
41
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
40
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
42
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
(-)linux-4.20/sound/soc/intel/boards/cht_cx2072x.c (+336 lines)
Line 0 Link Here
1
/*
2
 *  cht_cx207x.c - ASoc DPCM Machine driver for CherryTrail w/ CX2072x
3
 *
4
 *  Copyright (C) 2016 Intel Corp
5
 *  Author: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
6
 *
7
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; version 2 of the License.
12
 *
13
 *  This program is distributed in the hope that it will be useful, but
14
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 *  General Public License for more details.
17
 *
18
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19
 */
20
21
#include <linux/init.h>
22
#include <linux/module.h>
23
#include <linux/platform_device.h>
24
#include <linux/acpi.h>
25
#include <linux/device.h>
26
#include <linux/slab.h>
27
#include <asm/platform_sst_audio.h>
28
#include <sound/pcm.h>
29
#include <sound/pcm_params.h>
30
#include <sound/soc.h>
31
#include <sound/jack.h>
32
#include <sound/soc-acpi.h>
33
#include "../../codecs/cx2072x.h"
34
#include "../atom/sst-atom-controls.h"
35
36
static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
37
	SND_SOC_DAPM_HP("Headphone", NULL),
38
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
39
	SND_SOC_DAPM_MIC("Int Mic", NULL),
40
	SND_SOC_DAPM_SPK("Ext Spk", NULL),
41
};
42
43
static const struct snd_soc_dapm_route cht_audio_map[] = {
44
	/* External Speakers: HFL, HFR */
45
	{"Headphone", NULL, "PORTA"},
46
	{"Ext Spk", NULL, "PORTG"},
47
	{"PORTC", NULL, "Int Mic"},
48
	{"PORTD", NULL, "Headset Mic"},
49
50
	{"Playback", NULL, "ssp2 Tx"},
51
	{"ssp2 Tx", NULL, "codec_out0"},
52
	{"ssp2 Tx", NULL, "codec_out1"},
53
	{"codec_in0", NULL, "ssp2 Rx"},
54
	{"codec_in1", NULL, "ssp2 Rx"},
55
	{"ssp2 Rx", NULL, "Capture"},
56
	{"ssp0 Tx", NULL, "modem_out"},
57
	{"modem_in", NULL, "ssp0 Rx"},
58
};
59
60
static const struct snd_kcontrol_new cht_mc_controls[] = {
61
	SOC_DAPM_PIN_SWITCH("Headphone"),
62
	SOC_DAPM_PIN_SWITCH("Headset Mic"),
63
	SOC_DAPM_PIN_SWITCH("Int Mic"),
64
	SOC_DAPM_PIN_SWITCH("Ext Spk"),
65
};
66
67
static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
68
			     struct snd_pcm_hw_params *params)
69
{
70
	return 0;
71
}
72
73
static struct snd_soc_jack cht_cx_headset;
74
75
/* Headset jack detection DAPM pins */
76
static struct snd_soc_jack_pin cht_cx_headset_pins[] = {
77
	{
78
		.pin = "Headset Mic",
79
		.mask = SND_JACK_MICROPHONE,
80
	},
81
	{
82
		.pin = "Headphone",
83
		.mask = SND_JACK_HEADPHONE,
84
	},
85
};
86
87
static const struct acpi_gpio_params headset_gpios = { 0, 0, false };
88
89
static const struct acpi_gpio_mapping acpi_cht_cx2072x_gpios[] = {
90
	{ "headset-gpios", &headset_gpios, 1 },
91
	{},
92
};
93
94
static int cht_cx_jack_status_check(void *data)
95
{
96
	return cx2072x_get_jack_state(data);
97
}
98
99
static struct snd_soc_jack_gpio cht_cx_gpio = {
100
	.name = "headset",
101
	.report = SND_JACK_HEADSET | SND_JACK_BTN_0,
102
	.debounce_time = 150,
103
	.wake = true,
104
	.jack_status_check = cht_cx_jack_status_check,
105
};
106
107
static int cht_codec_init(struct snd_soc_pcm_runtime *rtd)
108
{
109
	int ret;
110
	struct snd_soc_card *card = rtd->card;
111
	struct snd_soc_component *component = rtd->codec_dai->component;
112
113
	if (devm_acpi_dev_add_driver_gpios(component->dev,
114
					   acpi_cht_cx2072x_gpios))
115
		dev_warn(rtd->dev, "Unable to add GPIO mapping table\n");
116
117
	card->dapm.idle_bias_off = true;
118
119
	/* set the default PLL rate, the clock is handled by the codec driver */
120
	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, CX2072X_MCLK_EXTERNAL_PLL,
121
				     19200000, SND_SOC_CLOCK_IN);
122
	if (ret) {
123
		dev_err(rtd->dev, "Could not set sysclk\n");
124
		return ret;
125
	}
126
127
	ret = snd_soc_card_jack_new(card, "Headset",
128
				    SND_JACK_HEADSET | SND_JACK_BTN_0,
129
				    &cht_cx_headset,
130
				    cht_cx_headset_pins,
131
				    ARRAY_SIZE(cht_cx_headset_pins));
132
	if (ret)
133
		return ret;
134
135
	cht_cx_gpio.gpiod_dev = component->dev;
136
	cht_cx_gpio.data = component;
137
138
	ret = snd_soc_jack_add_gpios(&cht_cx_headset, 1, &cht_cx_gpio);
139
	if (ret) {
140
		dev_err(rtd->dev, "Adding jack GPIO failed\n");
141
		return ret;
142
	}
143
144
	cx2072x_enable_detect(component);
145
146
	return ret;
147
}
148
149
static const struct snd_soc_pcm_stream cht_dai_params = {
150
	.formats = SNDRV_PCM_FMTBIT_S24_LE,
151
	.rate_min = 48000,
152
	.rate_max = 48000,
153
	.channels_min = 2,
154
	.channels_max = 2,
155
};
156
157
static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
158
			    struct snd_pcm_hw_params *params)
159
{
160
	struct snd_interval *rate = hw_param_interval(params,
161
			SNDRV_PCM_HW_PARAM_RATE);
162
	struct snd_interval *channels = hw_param_interval(params,
163
						SNDRV_PCM_HW_PARAM_CHANNELS);
164
	int ret;
165
166
	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
167
	rate->min = rate->max = 48000;
168
	channels->min = channels->max = 2;
169
170
	/* set SSP2 to 24-bit */
171
	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
172
173
	/*
174
	 * Default mode for SSP configuration is TDM 4 slot, override config
175
	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
176
	 * dai_set_tdm_slot() since there is no other API exposed
177
	 */
178
	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
179
				SND_SOC_DAIFMT_I2S     |
180
				SND_SOC_DAIFMT_NB_NF   |
181
				SND_SOC_DAIFMT_CBS_CFS);
182
	if (ret < 0) {
183
		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
184
		return ret;
185
	}
186
187
	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
188
	if (ret < 0) {
189
		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
190
		return ret;
191
	}
192
193
	snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50);
194
	return 0;
195
}
196
197
static const struct snd_soc_pcm_stream cht_cx_dai_params = {
198
	.formats = SNDRV_PCM_FMTBIT_S24_LE,
199
	.rate_min = 48000,
200
	.rate_max = 48000,
201
	.channels_min = 2,
202
	.channels_max = 2,
203
};
204
205
static int cht_aif1_startup(struct snd_pcm_substream *substream)
206
{
207
	return snd_pcm_hw_constraint_single(substream->runtime,
208
					SNDRV_PCM_HW_PARAM_RATE, 48000);
209
}
210
211
static struct snd_soc_ops cht_aif1_ops = {
212
	.startup = cht_aif1_startup,
213
};
214
215
static struct snd_soc_ops cht_be_ssp2_ops = {
216
	.hw_params = cht_aif1_hw_params,
217
};
218
219
static struct snd_soc_dai_link cht_dailink[] = {
220
	[MERR_DPCM_AUDIO] = {
221
		.name = "Audio Port",
222
		.stream_name = "Audio",
223
		.cpu_dai_name = "media-cpu-dai",
224
		.codec_dai_name = "snd-soc-dummy-dai",
225
		.codec_name = "snd-soc-dummy",
226
		.platform_name = "sst-mfld-platform",
227
		.nonatomic = true,
228
		.dynamic = 1,
229
		.dpcm_playback = 1,
230
		.dpcm_capture = 1,
231
		.ops = &cht_aif1_ops,
232
	},
233
	[MERR_DPCM_DEEP_BUFFER] = {
234
		.name = "Deep-Buffer Audio Port",
235
		.stream_name = "Deep-Buffer Audio",
236
		.cpu_dai_name = "deepbuffer-cpu-dai",
237
		.codec_dai_name = "snd-soc-dummy-dai",
238
		.codec_name = "snd-soc-dummy",
239
		.platform_name = "sst-mfld-platform",
240
		.nonatomic = true,
241
		.dynamic = 1,
242
		.dpcm_playback = 1,
243
		.ops = &cht_aif1_ops,
244
	},
245
	[MERR_DPCM_COMPR] = {
246
		.name = "Compressed Port",
247
		.stream_name = "Compress",
248
		.cpu_dai_name = "compress-cpu-dai",
249
		.codec_dai_name = "snd-soc-dummy-dai",
250
		.codec_name = "snd-soc-dummy",
251
		.platform_name = "sst-mfld-platform",
252
	},
253
	/* CODEC<->CODEC link */
254
	/* back ends */
255
	{
256
		.name = "SSP2-Codec",
257
		.id = 1,
258
		.cpu_dai_name = "ssp2-port",
259
		.platform_name = "sst-mfld-platform",
260
		.no_pcm = 1,
261
		.codec_dai_name = "cx2072x-hifi",
262
		.codec_name = "i2c-14F10720:00",
263
		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
264
					      | SND_SOC_DAIFMT_CBS_CFS,
265
		.init = cht_codec_init,
266
		.be_hw_params_fixup = cht_codec_fixup,
267
		.nonatomic = true,
268
		.dpcm_playback = 1,
269
		.dpcm_capture = 1,
270
		.ops = &cht_be_ssp2_ops,
271
	},
272
};
273
274
/* SoC card */
275
static struct snd_soc_card chtcx2072x_card = {
276
	.name = "chtcx2072x",
277
	.dai_link = cht_dailink,
278
	.num_links = ARRAY_SIZE(cht_dailink),
279
	.dapm_widgets = cht_dapm_widgets,
280
	.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
281
	.dapm_routes = cht_audio_map,
282
	.num_dapm_routes = ARRAY_SIZE(cht_audio_map),
283
	.controls = cht_mc_controls,
284
	.num_controls = ARRAY_SIZE(cht_mc_controls),
285
};
286
287
static char cht_cx_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
288
289
static int snd_cht_mc_probe(struct platform_device *pdev)
290
{
291
	int i;
292
	int dai_index;
293
	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
294
	const char *i2c_name = NULL;
295
296
	/* fix index of codec dai */
297
	dai_index = MERR_DPCM_COMPR + 1;
298
	for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
299
		if (!strcmp(cht_dailink[i].codec_name, "i2c-14F10720:00")) {
300
			dai_index = i;
301
			break;
302
		}
303
	}
304
305
	/* fixup codec name based on HID */
306
	i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
307
	if (i2c_name) {
308
		snprintf(cht_cx_codec_name, sizeof(cht_cx_codec_name),
309
			"%s%s", "i2c-", i2c_name);
310
		cht_dailink[dai_index].codec_name = cht_cx_codec_name;
311
	}
312
313
	/* register the soc card */
314
	chtcx2072x_card.dev = &pdev->dev;
315
	return devm_snd_soc_register_card(&pdev->dev, &chtcx2072x_card);
316
}
317
318
static int snd_cht_mc_remove(struct platform_device *pdev)
319
{
320
	snd_soc_jack_free_gpios(&cht_cx_headset, 1, &cht_cx_gpio);
321
	return 0;
322
}
323
324
static struct platform_driver snd_cht_mc_driver = {
325
	.driver = {
326
		.name = "cht-cx2072x",
327
	},
328
	.probe = snd_cht_mc_probe,
329
	.remove = snd_cht_mc_remove,
330
};
331
module_platform_driver(snd_cht_mc_driver);
332
333
MODULE_DESCRIPTION("ASoC Intel(R) Cherrytrail Machine driver");
334
MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
335
MODULE_LICENSE("GPL v2");
336
MODULE_ALIAS("platform:cht-cx2072x");
(-)linux-4.20/sound/soc/intel/common/soc-acpi-intel-cht-match.c (+9 lines)
Lines 118-123 Link Here
118
		.asoc_plat_name = "sst-mfld-platform",
118
		.asoc_plat_name = "sst-mfld-platform",
119
	},
119
	},
120
	{
120
	{
121
		.id = "14F10720",
122
		.drv_name = "cht-cx2072x",
123
		.fw_filename = "intel/fw_sst_22a8.bin",
124
		.board = "cht-bsw",
125
		.sof_fw_filename = "intel/reef-cht.ri",
126
		.sof_tplg_filename = "intel/reef-cht-cx2072cx.tplg",
127
		.asoc_plat_name = "sst-mfld-platform",
128
	},
129
	{
121
		.id = "10508824",
130
		.id = "10508824",
122
		.drv_name = "cht-bsw-nau8824",
131
		.drv_name = "cht-bsw-nau8824",
123
		.fw_filename = "intel/fw_sst_22a8.bin",
132
		.fw_filename = "intel/fw_sst_22a8.bin",
(-)linux-4.20/config-x86_64 (+2 lines)
Lines 6220-6225 Link Here
6220
CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
6330
CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
6221
CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
6331
CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
6222
CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=m
6332
CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=m
6333
CONFIG_SND_SOC_INTEL_CHT_CX2072X_MACH=m
6223
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
6334
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
6224
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
6335
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
6225
CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
6336
CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
Lines 6287-6292 Link Here
6287
CONFIG_SND_SOC_CS43130=m
6397
CONFIG_SND_SOC_CS43130=m
6288
CONFIG_SND_SOC_CS4349=m
6398
CONFIG_SND_SOC_CS4349=m
6289
CONFIG_SND_SOC_CS53L30=m
6399
CONFIG_SND_SOC_CS53L30=m
6400
CONFIG_SND_SOC_CX2072X=m
6290
CONFIG_SND_SOC_DA7213=m
6401
CONFIG_SND_SOC_DA7213=m
6291
CONFIG_SND_SOC_DA7219=m
6402
CONFIG_SND_SOC_DA7219=m
6292
CONFIG_SND_SOC_DMIC=m
6403
CONFIG_SND_SOC_DMIC=m

Return to bug 36374