1 // SPDX-License-Identifier: GPL-2.0
3 // ALSA SoC CX20721/CX20723 codec driver
5 // Copyright: (C) 2017 Conexant Systems, Inc.
6 // Author: Simon Ho, <Simon.ho@conexant.com>
8 // TODO: add support for TDM mode.
11 #include <linux/acpi.h>
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/gpio.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/slab.h>
23 #include <sound/core.h>
24 #include <sound/initval.h>
25 #include <sound/jack.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/tlv.h>
29 #include <sound/soc.h>
30 #include <sound/soc-dapm.h>
33 #define PLL_OUT_HZ_48 (1024 * 3 * 48000)
34 #define BITS_PER_SLOT 8
36 /* codec private data */
38 struct regmap
*regmap
;
40 unsigned int mclk_rate
;
42 struct snd_soc_component
*codec
;
43 struct snd_soc_jack_gpio jack_gpio
;
45 unsigned int bclk_ratio
;
62 static const DECLARE_TLV_DB_SCALE(adc_tlv
, -7400, 100, 0);
63 static const DECLARE_TLV_DB_SCALE(dac_tlv
, -7400, 100, 0);
64 static const DECLARE_TLV_DB_SCALE(boost_tlv
, 0, 1200, 0);
66 struct cx2072x_eq_ctrl
{
71 static const DECLARE_TLV_DB_RANGE(hpf_tlv
,
72 0, 0, TLV_DB_SCALE_ITEM(120, 0, 0),
73 1, 63, TLV_DB_SCALE_ITEM(30, 30, 0)
76 /* Lookup table for PRE_DIV */
93 * cx2072x register cache.
95 static const struct reg_default cx2072x_reg_defaults
[] = {
96 { CX2072X_AFG_POWER_STATE
, 0x00000003 },
97 { CX2072X_UM_RESPONSE
, 0x00000000 },
98 { CX2072X_GPIO_DATA
, 0x00000000 },
99 { CX2072X_GPIO_ENABLE
, 0x00000000 },
100 { CX2072X_GPIO_DIRECTION
, 0x00000000 },
101 { CX2072X_GPIO_WAKE
, 0x00000000 },
102 { CX2072X_GPIO_UM_ENABLE
, 0x00000000 },
103 { CX2072X_GPIO_STICKY_MASK
, 0x00000000 },
104 { CX2072X_DAC1_CONVERTER_FORMAT
, 0x00000031 },
105 { CX2072X_DAC1_AMP_GAIN_RIGHT
, 0x0000004a },
106 { CX2072X_DAC1_AMP_GAIN_LEFT
, 0x0000004a },
107 { CX2072X_DAC1_POWER_STATE
, 0x00000433 },
108 { CX2072X_DAC1_CONVERTER_STREAM_CHANNEL
, 0x00000000 },
109 { CX2072X_DAC1_EAPD_ENABLE
, 0x00000000 },
110 { CX2072X_DAC2_CONVERTER_FORMAT
, 0x00000031 },
111 { CX2072X_DAC2_AMP_GAIN_RIGHT
, 0x0000004a },
112 { CX2072X_DAC2_AMP_GAIN_LEFT
, 0x0000004a },
113 { CX2072X_DAC2_POWER_STATE
, 0x00000433 },
114 { CX2072X_DAC2_CONVERTER_STREAM_CHANNEL
, 0x00000000 },
115 { CX2072X_ADC1_CONVERTER_FORMAT
, 0x00000031 },
116 { CX2072X_ADC1_AMP_GAIN_RIGHT_0
, 0x0000004a },
117 { CX2072X_ADC1_AMP_GAIN_LEFT_0
, 0x0000004a },
118 { CX2072X_ADC1_AMP_GAIN_RIGHT_1
, 0x0000004a },
119 { CX2072X_ADC1_AMP_GAIN_LEFT_1
, 0x0000004a },
120 { CX2072X_ADC1_AMP_GAIN_RIGHT_2
, 0x0000004a },
121 { CX2072X_ADC1_AMP_GAIN_LEFT_2
, 0x0000004a },
122 { CX2072X_ADC1_AMP_GAIN_RIGHT_3
, 0x0000004a },
123 { CX2072X_ADC1_AMP_GAIN_LEFT_3
, 0x0000004a },
124 { CX2072X_ADC1_AMP_GAIN_RIGHT_4
, 0x0000004a },
125 { CX2072X_ADC1_AMP_GAIN_LEFT_4
, 0x0000004a },
126 { CX2072X_ADC1_AMP_GAIN_RIGHT_5
, 0x0000004a },
127 { CX2072X_ADC1_AMP_GAIN_LEFT_5
, 0x0000004a },
128 { CX2072X_ADC1_AMP_GAIN_RIGHT_6
, 0x0000004a },
129 { CX2072X_ADC1_AMP_GAIN_LEFT_6
, 0x0000004a },
130 { CX2072X_ADC1_CONNECTION_SELECT_CONTROL
, 0x00000000 },
131 { CX2072X_ADC1_POWER_STATE
, 0x00000433 },
132 { CX2072X_ADC1_CONVERTER_STREAM_CHANNEL
, 0x00000000 },
133 { CX2072X_ADC2_CONVERTER_FORMAT
, 0x00000031 },
134 { CX2072X_ADC2_AMP_GAIN_RIGHT_0
, 0x0000004a },
135 { CX2072X_ADC2_AMP_GAIN_LEFT_0
, 0x0000004a },
136 { CX2072X_ADC2_AMP_GAIN_RIGHT_1
, 0x0000004a },
137 { CX2072X_ADC2_AMP_GAIN_LEFT_1
, 0x0000004a },
138 { CX2072X_ADC2_AMP_GAIN_RIGHT_2
, 0x0000004a },
139 { CX2072X_ADC2_AMP_GAIN_LEFT_2
, 0x0000004a },
140 { CX2072X_ADC2_CONNECTION_SELECT_CONTROL
, 0x00000000 },
141 { CX2072X_ADC2_POWER_STATE
, 0x00000433 },
142 { CX2072X_ADC2_CONVERTER_STREAM_CHANNEL
, 0x00000000 },
143 { CX2072X_PORTA_CONNECTION_SELECT_CTRL
, 0x00000000 },
144 { CX2072X_PORTA_POWER_STATE
, 0x00000433 },
145 { CX2072X_PORTA_PIN_CTRL
, 0x000000c0 },
146 { CX2072X_PORTA_UNSOLICITED_RESPONSE
, 0x00000000 },
147 { CX2072X_PORTA_PIN_SENSE
, 0x00000000 },
148 { CX2072X_PORTA_EAPD_BTL
, 0x00000002 },
149 { CX2072X_PORTB_POWER_STATE
, 0x00000433 },
150 { CX2072X_PORTB_PIN_CTRL
, 0x00000000 },
151 { CX2072X_PORTB_UNSOLICITED_RESPONSE
, 0x00000000 },
152 { CX2072X_PORTB_PIN_SENSE
, 0x00000000 },
153 { CX2072X_PORTB_EAPD_BTL
, 0x00000002 },
154 { CX2072X_PORTB_GAIN_RIGHT
, 0x00000000 },
155 { CX2072X_PORTB_GAIN_LEFT
, 0x00000000 },
156 { CX2072X_PORTC_POWER_STATE
, 0x00000433 },
157 { CX2072X_PORTC_PIN_CTRL
, 0x00000000 },
158 { CX2072X_PORTC_GAIN_RIGHT
, 0x00000000 },
159 { CX2072X_PORTC_GAIN_LEFT
, 0x00000000 },
160 { CX2072X_PORTD_POWER_STATE
, 0x00000433 },
161 { CX2072X_PORTD_PIN_CTRL
, 0x00000020 },
162 { CX2072X_PORTD_UNSOLICITED_RESPONSE
, 0x00000000 },
163 { CX2072X_PORTD_PIN_SENSE
, 0x00000000 },
164 { CX2072X_PORTD_GAIN_RIGHT
, 0x00000000 },
165 { CX2072X_PORTD_GAIN_LEFT
, 0x00000000 },
166 { CX2072X_PORTE_CONNECTION_SELECT_CTRL
, 0x00000000 },
167 { CX2072X_PORTE_POWER_STATE
, 0x00000433 },
168 { CX2072X_PORTE_PIN_CTRL
, 0x00000040 },
169 { CX2072X_PORTE_UNSOLICITED_RESPONSE
, 0x00000000 },
170 { CX2072X_PORTE_PIN_SENSE
, 0x00000000 },
171 { CX2072X_PORTE_EAPD_BTL
, 0x00000002 },
172 { CX2072X_PORTE_GAIN_RIGHT
, 0x00000000 },
173 { CX2072X_PORTE_GAIN_LEFT
, 0x00000000 },
174 { CX2072X_PORTF_POWER_STATE
, 0x00000433 },
175 { CX2072X_PORTF_PIN_CTRL
, 0x00000000 },
176 { CX2072X_PORTF_UNSOLICITED_RESPONSE
, 0x00000000 },
177 { CX2072X_PORTF_PIN_SENSE
, 0x00000000 },
178 { CX2072X_PORTF_GAIN_RIGHT
, 0x00000000 },
179 { CX2072X_PORTF_GAIN_LEFT
, 0x00000000 },
180 { CX2072X_PORTG_POWER_STATE
, 0x00000433 },
181 { CX2072X_PORTG_PIN_CTRL
, 0x00000040 },
182 { CX2072X_PORTG_CONNECTION_SELECT_CTRL
, 0x00000000 },
183 { CX2072X_PORTG_EAPD_BTL
, 0x00000002 },
184 { CX2072X_PORTM_POWER_STATE
, 0x00000433 },
185 { CX2072X_PORTM_PIN_CTRL
, 0x00000000 },
186 { CX2072X_PORTM_CONNECTION_SELECT_CTRL
, 0x00000000 },
187 { CX2072X_PORTM_EAPD_BTL
, 0x00000002 },
188 { CX2072X_MIXER_POWER_STATE
, 0x00000433 },
189 { CX2072X_MIXER_GAIN_RIGHT_0
, 0x0000004a },
190 { CX2072X_MIXER_GAIN_LEFT_0
, 0x0000004a },
191 { CX2072X_MIXER_GAIN_RIGHT_1
, 0x0000004a },
192 { CX2072X_MIXER_GAIN_LEFT_1
, 0x0000004a },
193 { CX2072X_SPKR_DRC_ENABLE_STEP
, 0x040065a4 },
194 { CX2072X_SPKR_DRC_CONTROL
, 0x007b0024 },
195 { CX2072X_SPKR_DRC_TEST
, 0x00000000 },
196 { CX2072X_DIGITAL_BIOS_TEST0
, 0x001f008a },
197 { CX2072X_DIGITAL_BIOS_TEST2
, 0x00990026 },
198 { CX2072X_I2SPCM_CONTROL1
, 0x00010001 },
199 { CX2072X_I2SPCM_CONTROL2
, 0x00000000 },
200 { CX2072X_I2SPCM_CONTROL3
, 0x00000000 },
201 { CX2072X_I2SPCM_CONTROL4
, 0x00000000 },
202 { CX2072X_I2SPCM_CONTROL5
, 0x00000000 },
203 { CX2072X_I2SPCM_CONTROL6
, 0x00000000 },
204 { CX2072X_UM_INTERRUPT_CRTL_E
, 0x00000000 },
205 { CX2072X_CODEC_TEST2
, 0x00000000 },
206 { CX2072X_CODEC_TEST9
, 0x00000004 },
207 { CX2072X_CODEC_TEST20
, 0x00000600 },
208 { CX2072X_CODEC_TEST26
, 0x00000208 },
209 { CX2072X_ANALOG_TEST4
, 0x00000000 },
210 { CX2072X_ANALOG_TEST5
, 0x00000000 },
211 { CX2072X_ANALOG_TEST6
, 0x0000059a },
212 { CX2072X_ANALOG_TEST7
, 0x000000a7 },
213 { CX2072X_ANALOG_TEST8
, 0x00000017 },
214 { CX2072X_ANALOG_TEST9
, 0x00000000 },
215 { CX2072X_ANALOG_TEST10
, 0x00000285 },
216 { CX2072X_ANALOG_TEST11
, 0x00000000 },
217 { CX2072X_ANALOG_TEST12
, 0x00000000 },
218 { CX2072X_ANALOG_TEST13
, 0x00000000 },
219 { CX2072X_DIGITAL_TEST1
, 0x00000242 },
220 { CX2072X_DIGITAL_TEST11
, 0x00000000 },
221 { CX2072X_DIGITAL_TEST12
, 0x00000084 },
222 { CX2072X_DIGITAL_TEST15
, 0x00000077 },
223 { CX2072X_DIGITAL_TEST16
, 0x00000021 },
224 { CX2072X_DIGITAL_TEST17
, 0x00000018 },
225 { CX2072X_DIGITAL_TEST18
, 0x00000024 },
226 { CX2072X_DIGITAL_TEST19
, 0x00000001 },
227 { CX2072X_DIGITAL_TEST20
, 0x00000002 },
231 * register initialization
233 static const struct reg_sequence cx2072x_reg_init
[] = {
234 { CX2072X_ANALOG_TEST9
, 0x080 }, /* DC offset Calibration */
235 { CX2072X_CODEC_TEST26
, 0x65f }, /* Disable the PA */
236 { CX2072X_ANALOG_TEST10
, 0x289 }, /* Set the speaker output gain */
237 { CX2072X_CODEC_TEST20
, 0xf05 },
238 { CX2072X_CODEC_TESTXX
, 0x380 },
239 { CX2072X_CODEC_TEST26
, 0xb90 },
240 { CX2072X_CODEC_TEST9
, 0x001 }, /* Enable 30 Hz High pass filter */
241 { CX2072X_ANALOG_TEST3
, 0x300 }, /* Disable PCBEEP pad */
242 { CX2072X_CODEC_TEST24
, 0x100 }, /* Disable SnM mode */
243 { CX2072X_PORTD_PIN_CTRL
, 0x020 }, /* Enable PortD input */
244 { CX2072X_GPIO_ENABLE
, 0x040 }, /* Enable GPIO7 pin for button */
245 { CX2072X_GPIO_UM_ENABLE
, 0x040 }, /* Enable UM for GPIO7 */
246 { CX2072X_UM_RESPONSE
, 0x080 }, /* Enable button response */
247 { CX2072X_DIGITAL_TEST12
, 0x0c4 }, /* Enable headset button */
248 { CX2072X_DIGITAL_TEST0
, 0x415 }, /* Power down class-D during idle */
249 { CX2072X_I2SPCM_CONTROL2
, 0x00f }, /* Enable I2S TX */
250 { CX2072X_I2SPCM_CONTROL3
, 0x00f }, /* Enable I2S RX */
253 static unsigned int cx2072x_register_size(unsigned int reg
)
256 case CX2072X_VENDOR_ID
:
257 case CX2072X_REVISION_ID
:
258 case CX2072X_PORTA_PIN_SENSE
:
259 case CX2072X_PORTB_PIN_SENSE
:
260 case CX2072X_PORTD_PIN_SENSE
:
261 case CX2072X_PORTE_PIN_SENSE
:
262 case CX2072X_PORTF_PIN_SENSE
:
263 case CX2072X_I2SPCM_CONTROL1
:
264 case CX2072X_I2SPCM_CONTROL2
:
265 case CX2072X_I2SPCM_CONTROL3
:
266 case CX2072X_I2SPCM_CONTROL4
:
267 case CX2072X_I2SPCM_CONTROL5
:
268 case CX2072X_I2SPCM_CONTROL6
:
269 case CX2072X_UM_INTERRUPT_CRTL_E
:
270 case CX2072X_EQ_G_COEFF
:
271 case CX2072X_SPKR_DRC_CONTROL
:
272 case CX2072X_SPKR_DRC_TEST
:
273 case CX2072X_DIGITAL_BIOS_TEST0
:
274 case CX2072X_DIGITAL_BIOS_TEST2
:
276 case CX2072X_EQ_ENABLE_BYPASS
:
277 case CX2072X_EQ_B0_COEFF
:
278 case CX2072X_EQ_B1_COEFF
:
279 case CX2072X_EQ_B2_COEFF
:
280 case CX2072X_EQ_A1_COEFF
:
281 case CX2072X_EQ_A2_COEFF
:
282 case CX2072X_DAC1_CONVERTER_FORMAT
:
283 case CX2072X_DAC2_CONVERTER_FORMAT
:
284 case CX2072X_ADC1_CONVERTER_FORMAT
:
285 case CX2072X_ADC2_CONVERTER_FORMAT
:
286 case CX2072X_CODEC_TEST2
:
287 case CX2072X_CODEC_TEST9
:
288 case CX2072X_CODEC_TEST20
:
289 case CX2072X_CODEC_TEST26
:
290 case CX2072X_ANALOG_TEST3
:
291 case CX2072X_ANALOG_TEST4
:
292 case CX2072X_ANALOG_TEST5
:
293 case CX2072X_ANALOG_TEST6
:
294 case CX2072X_ANALOG_TEST7
:
295 case CX2072X_ANALOG_TEST8
:
296 case CX2072X_ANALOG_TEST9
:
297 case CX2072X_ANALOG_TEST10
:
298 case CX2072X_ANALOG_TEST11
:
299 case CX2072X_ANALOG_TEST12
:
300 case CX2072X_ANALOG_TEST13
:
301 case CX2072X_DIGITAL_TEST0
:
302 case CX2072X_DIGITAL_TEST1
:
303 case CX2072X_DIGITAL_TEST11
:
304 case CX2072X_DIGITAL_TEST12
:
305 case CX2072X_DIGITAL_TEST15
:
306 case CX2072X_DIGITAL_TEST16
:
307 case CX2072X_DIGITAL_TEST17
:
308 case CX2072X_DIGITAL_TEST18
:
309 case CX2072X_DIGITAL_TEST19
:
310 case CX2072X_DIGITAL_TEST20
:
317 static bool cx2072x_readable_register(struct device
*dev
, unsigned int reg
)
320 case CX2072X_VENDOR_ID
:
321 case CX2072X_REVISION_ID
:
322 case CX2072X_CURRENT_BCLK_FREQUENCY
:
323 case CX2072X_AFG_POWER_STATE
:
324 case CX2072X_UM_RESPONSE
:
325 case CX2072X_GPIO_DATA
:
326 case CX2072X_GPIO_ENABLE
:
327 case CX2072X_GPIO_DIRECTION
:
328 case CX2072X_GPIO_WAKE
:
329 case CX2072X_GPIO_UM_ENABLE
:
330 case CX2072X_GPIO_STICKY_MASK
:
331 case CX2072X_DAC1_CONVERTER_FORMAT
:
332 case CX2072X_DAC1_AMP_GAIN_RIGHT
:
333 case CX2072X_DAC1_AMP_GAIN_LEFT
:
334 case CX2072X_DAC1_POWER_STATE
:
335 case CX2072X_DAC1_CONVERTER_STREAM_CHANNEL
:
336 case CX2072X_DAC1_EAPD_ENABLE
:
337 case CX2072X_DAC2_CONVERTER_FORMAT
:
338 case CX2072X_DAC2_AMP_GAIN_RIGHT
:
339 case CX2072X_DAC2_AMP_GAIN_LEFT
:
340 case CX2072X_DAC2_POWER_STATE
:
341 case CX2072X_DAC2_CONVERTER_STREAM_CHANNEL
:
342 case CX2072X_ADC1_CONVERTER_FORMAT
:
343 case CX2072X_ADC1_AMP_GAIN_RIGHT_0
:
344 case CX2072X_ADC1_AMP_GAIN_LEFT_0
:
345 case CX2072X_ADC1_AMP_GAIN_RIGHT_1
:
346 case CX2072X_ADC1_AMP_GAIN_LEFT_1
:
347 case CX2072X_ADC1_AMP_GAIN_RIGHT_2
:
348 case CX2072X_ADC1_AMP_GAIN_LEFT_2
:
349 case CX2072X_ADC1_AMP_GAIN_RIGHT_3
:
350 case CX2072X_ADC1_AMP_GAIN_LEFT_3
:
351 case CX2072X_ADC1_AMP_GAIN_RIGHT_4
:
352 case CX2072X_ADC1_AMP_GAIN_LEFT_4
:
353 case CX2072X_ADC1_AMP_GAIN_RIGHT_5
:
354 case CX2072X_ADC1_AMP_GAIN_LEFT_5
:
355 case CX2072X_ADC1_AMP_GAIN_RIGHT_6
:
356 case CX2072X_ADC1_AMP_GAIN_LEFT_6
:
357 case CX2072X_ADC1_CONNECTION_SELECT_CONTROL
:
358 case CX2072X_ADC1_POWER_STATE
:
359 case CX2072X_ADC1_CONVERTER_STREAM_CHANNEL
:
360 case CX2072X_ADC2_CONVERTER_FORMAT
:
361 case CX2072X_ADC2_AMP_GAIN_RIGHT_0
:
362 case CX2072X_ADC2_AMP_GAIN_LEFT_0
:
363 case CX2072X_ADC2_AMP_GAIN_RIGHT_1
:
364 case CX2072X_ADC2_AMP_GAIN_LEFT_1
:
365 case CX2072X_ADC2_AMP_GAIN_RIGHT_2
:
366 case CX2072X_ADC2_AMP_GAIN_LEFT_2
:
367 case CX2072X_ADC2_CONNECTION_SELECT_CONTROL
:
368 case CX2072X_ADC2_POWER_STATE
:
369 case CX2072X_ADC2_CONVERTER_STREAM_CHANNEL
:
370 case CX2072X_PORTA_CONNECTION_SELECT_CTRL
:
371 case CX2072X_PORTA_POWER_STATE
:
372 case CX2072X_PORTA_PIN_CTRL
:
373 case CX2072X_PORTA_UNSOLICITED_RESPONSE
:
374 case CX2072X_PORTA_PIN_SENSE
:
375 case CX2072X_PORTA_EAPD_BTL
:
376 case CX2072X_PORTB_POWER_STATE
:
377 case CX2072X_PORTB_PIN_CTRL
:
378 case CX2072X_PORTB_UNSOLICITED_RESPONSE
:
379 case CX2072X_PORTB_PIN_SENSE
:
380 case CX2072X_PORTB_EAPD_BTL
:
381 case CX2072X_PORTB_GAIN_RIGHT
:
382 case CX2072X_PORTB_GAIN_LEFT
:
383 case CX2072X_PORTC_POWER_STATE
:
384 case CX2072X_PORTC_PIN_CTRL
:
385 case CX2072X_PORTC_GAIN_RIGHT
:
386 case CX2072X_PORTC_GAIN_LEFT
:
387 case CX2072X_PORTD_POWER_STATE
:
388 case CX2072X_PORTD_PIN_CTRL
:
389 case CX2072X_PORTD_UNSOLICITED_RESPONSE
:
390 case CX2072X_PORTD_PIN_SENSE
:
391 case CX2072X_PORTD_GAIN_RIGHT
:
392 case CX2072X_PORTD_GAIN_LEFT
:
393 case CX2072X_PORTE_CONNECTION_SELECT_CTRL
:
394 case CX2072X_PORTE_POWER_STATE
:
395 case CX2072X_PORTE_PIN_CTRL
:
396 case CX2072X_PORTE_UNSOLICITED_RESPONSE
:
397 case CX2072X_PORTE_PIN_SENSE
:
398 case CX2072X_PORTE_EAPD_BTL
:
399 case CX2072X_PORTE_GAIN_RIGHT
:
400 case CX2072X_PORTE_GAIN_LEFT
:
401 case CX2072X_PORTF_POWER_STATE
:
402 case CX2072X_PORTF_PIN_CTRL
:
403 case CX2072X_PORTF_UNSOLICITED_RESPONSE
:
404 case CX2072X_PORTF_PIN_SENSE
:
405 case CX2072X_PORTF_GAIN_RIGHT
:
406 case CX2072X_PORTF_GAIN_LEFT
:
407 case CX2072X_PORTG_POWER_STATE
:
408 case CX2072X_PORTG_PIN_CTRL
:
409 case CX2072X_PORTG_CONNECTION_SELECT_CTRL
:
410 case CX2072X_PORTG_EAPD_BTL
:
411 case CX2072X_PORTM_POWER_STATE
:
412 case CX2072X_PORTM_PIN_CTRL
:
413 case CX2072X_PORTM_CONNECTION_SELECT_CTRL
:
414 case CX2072X_PORTM_EAPD_BTL
:
415 case CX2072X_MIXER_POWER_STATE
:
416 case CX2072X_MIXER_GAIN_RIGHT_0
:
417 case CX2072X_MIXER_GAIN_LEFT_0
:
418 case CX2072X_MIXER_GAIN_RIGHT_1
:
419 case CX2072X_MIXER_GAIN_LEFT_1
:
420 case CX2072X_EQ_ENABLE_BYPASS
:
421 case CX2072X_EQ_B0_COEFF
:
422 case CX2072X_EQ_B1_COEFF
:
423 case CX2072X_EQ_B2_COEFF
:
424 case CX2072X_EQ_A1_COEFF
:
425 case CX2072X_EQ_A2_COEFF
:
426 case CX2072X_EQ_G_COEFF
:
427 case CX2072X_SPKR_DRC_ENABLE_STEP
:
428 case CX2072X_SPKR_DRC_CONTROL
:
429 case CX2072X_SPKR_DRC_TEST
:
430 case CX2072X_DIGITAL_BIOS_TEST0
:
431 case CX2072X_DIGITAL_BIOS_TEST2
:
432 case CX2072X_I2SPCM_CONTROL1
:
433 case CX2072X_I2SPCM_CONTROL2
:
434 case CX2072X_I2SPCM_CONTROL3
:
435 case CX2072X_I2SPCM_CONTROL4
:
436 case CX2072X_I2SPCM_CONTROL5
:
437 case CX2072X_I2SPCM_CONTROL6
:
438 case CX2072X_UM_INTERRUPT_CRTL_E
:
439 case CX2072X_CODEC_TEST2
:
440 case CX2072X_CODEC_TEST9
:
441 case CX2072X_CODEC_TEST20
:
442 case CX2072X_CODEC_TEST26
:
443 case CX2072X_ANALOG_TEST4
:
444 case CX2072X_ANALOG_TEST5
:
445 case CX2072X_ANALOG_TEST6
:
446 case CX2072X_ANALOG_TEST7
:
447 case CX2072X_ANALOG_TEST8
:
448 case CX2072X_ANALOG_TEST9
:
449 case CX2072X_ANALOG_TEST10
:
450 case CX2072X_ANALOG_TEST11
:
451 case CX2072X_ANALOG_TEST12
:
452 case CX2072X_ANALOG_TEST13
:
453 case CX2072X_DIGITAL_TEST0
:
454 case CX2072X_DIGITAL_TEST1
:
455 case CX2072X_DIGITAL_TEST11
:
456 case CX2072X_DIGITAL_TEST12
:
457 case CX2072X_DIGITAL_TEST15
:
458 case CX2072X_DIGITAL_TEST16
:
459 case CX2072X_DIGITAL_TEST17
:
460 case CX2072X_DIGITAL_TEST18
:
461 case CX2072X_DIGITAL_TEST19
:
462 case CX2072X_DIGITAL_TEST20
:
469 static bool cx2072x_volatile_register(struct device
*dev
, unsigned int reg
)
472 case CX2072X_VENDOR_ID
:
473 case CX2072X_REVISION_ID
:
474 case CX2072X_UM_INTERRUPT_CRTL_E
:
475 case CX2072X_DIGITAL_TEST11
:
476 case CX2072X_PORTA_PIN_SENSE
:
477 case CX2072X_PORTB_PIN_SENSE
:
478 case CX2072X_PORTD_PIN_SENSE
:
479 case CX2072X_PORTE_PIN_SENSE
:
480 case CX2072X_PORTF_PIN_SENSE
:
481 case CX2072X_EQ_G_COEFF
:
482 case CX2072X_EQ_BAND
:
489 static int cx2072x_reg_raw_write(struct i2c_client
*client
,
491 const void *val
, size_t val_count
)
493 struct device
*dev
= &client
->dev
;
494 u8 buf
[2 + CX2072X_MAX_EQ_COEFF
];
497 if (WARN_ON(val_count
+ 2 > sizeof(buf
)))
503 memcpy(buf
+ 2, val
, val_count
);
505 ret
= i2c_master_send(client
, buf
, val_count
+ 2);
506 if (ret
!= val_count
+ 2) {
507 dev_err(dev
, "I2C write failed, ret = %d\n", ret
);
508 return ret
< 0 ? ret
: -EIO
;
513 static int cx2072x_reg_write(void *context
, unsigned int reg
,
519 size
= cx2072x_register_size(reg
);
521 if (reg
== CX2072X_UM_INTERRUPT_CRTL_E
) {
522 /* Update the MSB byte only */
528 raw_value
= cpu_to_le32(value
);
529 return cx2072x_reg_raw_write(context
, reg
, &raw_value
, size
);
532 static int cx2072x_reg_read(void *context
, unsigned int reg
,
535 struct i2c_client
*client
= context
;
536 struct device
*dev
= &client
->dev
;
538 struct i2c_msg msgs
[2];
543 size
= cx2072x_register_size(reg
);
545 send_buf
[0] = reg
>> 8;
546 send_buf
[1] = reg
& 0xff;
548 msgs
[0].addr
= client
->addr
;
549 msgs
[0].len
= sizeof(send_buf
);
550 msgs
[0].buf
= send_buf
;
553 msgs
[1].addr
= client
->addr
;
555 msgs
[1].buf
= (u8
*)&recv_buf
;
556 msgs
[1].flags
= I2C_M_RD
;
558 ret
= i2c_transfer(client
->adapter
, msgs
, ARRAY_SIZE(msgs
));
559 if (ret
!= ARRAY_SIZE(msgs
)) {
560 dev_err(dev
, "Failed to read register, ret = %d\n", ret
);
561 return ret
< 0 ? ret
: -EIO
;
564 *value
= le32_to_cpu(recv_buf
);
568 /* get suggested pre_div valuce from mclk frequency */
569 static unsigned int get_div_from_mclk(unsigned int mclk
)
571 unsigned int div
= 8;
574 for (i
= 0; i
< ARRAY_SIZE(mclk_pre_div
); i
++) {
575 if (mclk
<= mclk_pre_div
[i
].mclk
) {
576 div
= mclk_pre_div
[i
].div
;
583 static int cx2072x_config_pll(struct cx2072x_priv
*cx2072x
)
585 struct device
*dev
= cx2072x
->dev
;
586 unsigned int pre_div
;
587 unsigned int pre_div_val
;
588 unsigned int pll_input
;
589 unsigned int pll_output
;
590 unsigned int int_div
;
591 unsigned int frac_div
;
594 unsigned int sample_rate
= cx2072x
->sample_rate
;
595 int pt_sample_per_sync
= 2;
596 int pt_clock_per_sample
= 96;
598 switch (sample_rate
) {
606 pt_sample_per_sync
= 1;
607 pt_clock_per_sample
= 48;
611 pt_sample_per_sync
= 0;
612 pt_clock_per_sample
= 24;
616 dev_err(dev
, "Unsupported sample rate %d\n", sample_rate
);
620 /* Configure PLL settings */
621 pre_div
= get_div_from_mclk(cx2072x
->mclk_rate
);
622 pll_input
= cx2072x
->mclk_rate
/ pre_div
;
623 pll_output
= sample_rate
* 3072;
624 int_div
= pll_output
/ pll_input
;
625 frac_div
= pll_output
- (int_div
* pll_input
);
629 frac_div
/= pll_input
;
630 frac_num
= (u64
)(4000 + frac_div
) * ((1 << 20) - 4);
632 frac
= ((u32
)frac_num
+ 499) / 1000;
634 pre_div_val
= (pre_div
- 1) * 2;
636 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST4
,
637 0x40 | (pre_div_val
<< 8));
640 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST7
, 0x100);
643 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST6
,
645 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST7
,
650 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST8
, int_div
);
652 /* configure PLL tracking */
654 /* disable PLL tracking */
655 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST16
, 0x00);
657 /* configure and enable PLL tracking */
658 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST16
,
659 (pt_sample_per_sync
<< 4) & 0xf0);
660 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST17
,
661 pt_clock_per_sample
);
662 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST18
,
663 pt_clock_per_sample
* 3 / 2);
664 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST19
, 0x01);
665 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST20
, 0x02);
666 regmap_update_bits(cx2072x
->regmap
, CX2072X_DIGITAL_TEST16
,
673 static int cx2072x_config_i2spcm(struct cx2072x_priv
*cx2072x
)
675 struct device
*dev
= cx2072x
->dev
;
676 unsigned int bclk_rate
= 0;
678 int has_one_bit_delay
= 0;
679 int is_frame_inv
= 0;
682 int frame_len
= cx2072x
->frame_size
;
683 int sample_size
= cx2072x
->sample_size
;
685 int i2s_right_pause_interval
= 0;
686 int i2s_right_pause_pos
;
687 int is_big_endian
= 1;
690 union cx2072x_reg_i2spcm_ctrl_reg1 reg1
;
691 union cx2072x_reg_i2spcm_ctrl_reg2 reg2
;
692 union cx2072x_reg_i2spcm_ctrl_reg3 reg3
;
693 union cx2072x_reg_i2spcm_ctrl_reg4 reg4
;
694 union cx2072x_reg_i2spcm_ctrl_reg5 reg5
;
695 union cx2072x_reg_i2spcm_ctrl_reg6 reg6
;
696 union cx2072x_reg_digital_bios_test2 regdbt2
;
697 const unsigned int fmt
= cx2072x
->dai_fmt
;
699 if (frame_len
<= 0) {
700 dev_err(dev
, "Incorrect frame len %d\n", frame_len
);
704 if (sample_size
<= 0) {
705 dev_err(dev
, "Incorrect sample size %d\n", sample_size
);
709 dev_dbg(dev
, "config_i2spcm set_dai_fmt- %08x\n", fmt
);
711 regdbt2
.ulval
= 0xac;
713 /* set master/slave */
714 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
715 case SND_SOC_DAIFMT_CBM_CFM
:
716 reg2
.r
.tx_master
= 1;
717 reg3
.r
.rx_master
= 1;
718 dev_dbg(dev
, "Sets Master mode\n");
721 case SND_SOC_DAIFMT_CBS_CFS
:
722 reg2
.r
.tx_master
= 0;
723 reg3
.r
.rx_master
= 0;
724 dev_dbg(dev
, "Sets Slave mode\n");
728 dev_err(dev
, "Unsupported DAI master mode\n");
733 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
734 case SND_SOC_DAIFMT_I2S
:
736 has_one_bit_delay
= 1;
737 pulse_len
= frame_len
/ 2;
740 case SND_SOC_DAIFMT_RIGHT_J
:
742 pulse_len
= frame_len
/ 2;
745 case SND_SOC_DAIFMT_LEFT_J
:
747 pulse_len
= frame_len
/ 2;
751 dev_err(dev
, "Unsupported DAI format\n");
755 /* clock inversion */
756 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
757 case SND_SOC_DAIFMT_NB_NF
:
758 is_frame_inv
= is_i2s
;
759 is_bclk_inv
= is_i2s
;
762 case SND_SOC_DAIFMT_IB_IF
:
763 is_frame_inv
= !is_i2s
;
764 is_bclk_inv
= !is_i2s
;
767 case SND_SOC_DAIFMT_IB_NF
:
768 is_frame_inv
= is_i2s
;
769 is_bclk_inv
= !is_i2s
;
772 case SND_SOC_DAIFMT_NB_IF
:
773 is_frame_inv
= !is_i2s
;
774 is_bclk_inv
= is_i2s
;
778 dev_err(dev
, "Unsupported DAI clock inversion\n");
782 reg1
.r
.rx_data_one_line
= 1;
783 reg1
.r
.tx_data_one_line
= 1;
786 i2s_right_slot
= (frame_len
/ 2) / BITS_PER_SLOT
;
787 i2s_right_pause_interval
= (frame_len
/ 2) % BITS_PER_SLOT
;
788 i2s_right_pause_pos
= i2s_right_slot
* BITS_PER_SLOT
;
791 reg1
.r
.rx_ws_pol
= is_frame_inv
;
792 reg1
.r
.rx_ws_wid
= pulse_len
- 1;
794 reg1
.r
.rx_frm_len
= frame_len
/ BITS_PER_SLOT
- 1;
795 reg1
.r
.rx_sa_size
= (sample_size
/ BITS_PER_SLOT
) - 1;
797 reg1
.r
.tx_ws_pol
= reg1
.r
.rx_ws_pol
;
798 reg1
.r
.tx_ws_wid
= pulse_len
- 1;
799 reg1
.r
.tx_frm_len
= reg1
.r
.rx_frm_len
;
800 reg1
.r
.tx_sa_size
= reg1
.r
.rx_sa_size
;
802 reg2
.r
.tx_endian_sel
= !is_big_endian
;
803 reg2
.r
.tx_dstart_dly
= has_one_bit_delay
;
804 if (cx2072x
->en_aec_ref
)
805 reg2
.r
.tx_dstart_dly
= 0;
807 reg3
.r
.rx_endian_sel
= !is_big_endian
;
808 reg3
.r
.rx_dstart_dly
= has_one_bit_delay
;
813 reg2
.r
.tx_slot_1
= 0;
814 reg2
.r
.tx_slot_2
= i2s_right_slot
;
815 reg3
.r
.rx_slot_1
= 0;
816 if (cx2072x
->en_aec_ref
)
817 reg3
.r
.rx_slot_2
= 0;
819 reg3
.r
.rx_slot_2
= i2s_right_slot
;
820 reg6
.r
.rx_pause_start_pos
= i2s_right_pause_pos
;
821 reg6
.r
.rx_pause_cycles
= i2s_right_pause_interval
;
822 reg6
.r
.tx_pause_start_pos
= i2s_right_pause_pos
;
823 reg6
.r
.tx_pause_cycles
= i2s_right_pause_interval
;
825 dev_err(dev
, "TDM mode is not implemented yet\n");
828 regdbt2
.r
.i2s_bclk_invert
= is_bclk_inv
;
830 reg1
.r
.rx_data_one_line
= 1;
831 reg1
.r
.tx_data_one_line
= 1;
833 /* Configures the BCLK output */
834 bclk_rate
= cx2072x
->sample_rate
* frame_len
;
835 reg5
.r
.i2s_pcm_clk_div_chan_en
= 0;
837 /* Disables bclk output before setting new value */
838 regmap_write(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL5
, 0);
840 if (reg2
.r
.tx_master
) {
841 /* Configures BCLK rate */
843 mod
= do_div(div
, bclk_rate
);
845 dev_err(dev
, "Unsupported BCLK %dHz\n", bclk_rate
);
848 dev_dbg(dev
, "enables BCLK %dHz output\n", bclk_rate
);
849 reg5
.r
.i2s_pcm_clk_div
= (u32
)div
- 1;
850 reg5
.r
.i2s_pcm_clk_div_chan_en
= 1;
853 regmap_write(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL1
, reg1
.ulval
);
854 regmap_update_bits(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL2
, 0xffffffc0,
856 regmap_update_bits(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL3
, 0xffffffc0,
858 regmap_write(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL4
, reg4
.ulval
);
859 regmap_write(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL6
, reg6
.ulval
);
860 regmap_write(cx2072x
->regmap
, CX2072X_I2SPCM_CONTROL5
, reg5
.ulval
);
862 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_BIOS_TEST2
,
868 static int afg_power_ev(struct snd_soc_dapm_widget
*w
,
869 struct snd_kcontrol
*kcontrol
, int event
)
871 struct snd_soc_component
*codec
= snd_soc_dapm_to_component(w
->dapm
);
872 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
875 case SND_SOC_DAPM_POST_PMU
:
876 regmap_update_bits(cx2072x
->regmap
, CX2072X_DIGITAL_BIOS_TEST0
,
880 case SND_SOC_DAPM_PRE_PMD
:
881 regmap_update_bits(cx2072x
->regmap
, CX2072X_DIGITAL_BIOS_TEST0
,
889 static const struct snd_kcontrol_new cx2072x_snd_controls
[] = {
890 SOC_DOUBLE_R_TLV("PortD Boost Volume", CX2072X_PORTD_GAIN_LEFT
,
891 CX2072X_PORTD_GAIN_RIGHT
, 0, 3, 0, boost_tlv
),
892 SOC_DOUBLE_R_TLV("PortC Boost Volume", CX2072X_PORTC_GAIN_LEFT
,
893 CX2072X_PORTC_GAIN_RIGHT
, 0, 3, 0, boost_tlv
),
894 SOC_DOUBLE_R_TLV("PortB Boost Volume", CX2072X_PORTB_GAIN_LEFT
,
895 CX2072X_PORTB_GAIN_RIGHT
, 0, 3, 0, boost_tlv
),
896 SOC_DOUBLE_R_TLV("PortD ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_1
,
897 CX2072X_ADC1_AMP_GAIN_RIGHT_1
, 0, 0x4a, 0, adc_tlv
),
898 SOC_DOUBLE_R_TLV("PortC ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_2
,
899 CX2072X_ADC1_AMP_GAIN_RIGHT_2
, 0, 0x4a, 0, adc_tlv
),
900 SOC_DOUBLE_R_TLV("PortB ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_0
,
901 CX2072X_ADC1_AMP_GAIN_RIGHT_0
, 0, 0x4a, 0, adc_tlv
),
902 SOC_DOUBLE_R_TLV("DAC1 Volume", CX2072X_DAC1_AMP_GAIN_LEFT
,
903 CX2072X_DAC1_AMP_GAIN_RIGHT
, 0, 0x4a, 0, dac_tlv
),
904 SOC_DOUBLE_R("DAC1 Switch", CX2072X_DAC1_AMP_GAIN_LEFT
,
905 CX2072X_DAC1_AMP_GAIN_RIGHT
, 7, 1, 0),
906 SOC_DOUBLE_R_TLV("DAC2 Volume", CX2072X_DAC2_AMP_GAIN_LEFT
,
907 CX2072X_DAC2_AMP_GAIN_RIGHT
, 0, 0x4a, 0, dac_tlv
),
908 SOC_SINGLE_TLV("HPF Freq", CX2072X_CODEC_TEST9
, 0, 0x3f, 0, hpf_tlv
),
909 SOC_DOUBLE("HPF Switch", CX2072X_CODEC_TEST9
, 8, 9, 1, 1),
910 SOC_SINGLE("PortA HP Amp Switch", CX2072X_PORTA_PIN_CTRL
, 7, 1, 0),
913 static int cx2072x_hw_params(struct snd_pcm_substream
*substream
,
914 struct snd_pcm_hw_params
*params
,
915 struct snd_soc_dai
*dai
)
917 struct snd_soc_component
*codec
= dai
->component
;
918 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
919 struct device
*dev
= codec
->dev
;
920 const unsigned int sample_rate
= params_rate(params
);
921 int sample_size
, frame_size
;
923 /* Data sizes if not using TDM */
924 sample_size
= params_width(params
);
929 frame_size
= snd_soc_params_to_frame_size(params
);
933 if (cx2072x
->mclk_rate
== 0) {
934 dev_err(dev
, "Master clock rate is not configured\n");
938 if (cx2072x
->bclk_ratio
)
939 frame_size
= cx2072x
->bclk_ratio
;
941 switch (sample_rate
) {
951 dev_err(dev
, "Unsupported sample rate %d\n", sample_rate
);
955 dev_dbg(dev
, "Sample size %d bits, frame = %d bits, rate = %d Hz\n",
956 sample_size
, frame_size
, sample_rate
);
958 cx2072x
->frame_size
= frame_size
;
959 cx2072x
->sample_size
= sample_size
;
960 cx2072x
->sample_rate
= sample_rate
;
962 if (dai
->id
== CX2072X_DAI_DSP
) {
963 cx2072x
->en_aec_ref
= true;
964 dev_dbg(cx2072x
->dev
, "enables aec reference\n");
965 regmap_write(cx2072x
->regmap
,
966 CX2072X_ADC1_CONNECTION_SELECT_CONTROL
, 3);
969 if (cx2072x
->pll_changed
) {
970 cx2072x_config_pll(cx2072x
);
971 cx2072x
->pll_changed
= false;
974 if (cx2072x
->i2spcm_changed
) {
975 cx2072x_config_i2spcm(cx2072x
);
976 cx2072x
->i2spcm_changed
= false;
982 static int cx2072x_set_dai_bclk_ratio(struct snd_soc_dai
*dai
,
985 struct snd_soc_component
*codec
= dai
->component
;
986 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
988 cx2072x
->bclk_ratio
= ratio
;
992 static int cx2072x_set_dai_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
993 unsigned int freq
, int dir
)
995 struct snd_soc_component
*codec
= dai
->component
;
996 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
998 if (clk_set_rate(cx2072x
->mclk
, freq
)) {
999 dev_err(codec
->dev
, "set clk rate failed\n");
1003 cx2072x
->mclk_rate
= freq
;
1007 static int cx2072x_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
1009 struct snd_soc_component
*codec
= dai
->component
;
1010 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1011 struct device
*dev
= codec
->dev
;
1013 dev_dbg(dev
, "set_dai_fmt- %08x\n", fmt
);
1014 /* set master/slave */
1015 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
1016 case SND_SOC_DAIFMT_CBM_CFM
:
1017 case SND_SOC_DAIFMT_CBS_CFS
:
1021 dev_err(dev
, "Unsupported DAI master mode\n");
1026 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
1027 case SND_SOC_DAIFMT_I2S
:
1028 case SND_SOC_DAIFMT_RIGHT_J
:
1029 case SND_SOC_DAIFMT_LEFT_J
:
1033 dev_err(dev
, "Unsupported DAI format\n");
1037 /* clock inversion */
1038 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
1039 case SND_SOC_DAIFMT_NB_NF
:
1040 case SND_SOC_DAIFMT_IB_IF
:
1041 case SND_SOC_DAIFMT_IB_NF
:
1042 case SND_SOC_DAIFMT_NB_IF
:
1046 dev_err(dev
, "Unsupported DAI clock inversion\n");
1050 cx2072x
->dai_fmt
= fmt
;
1054 static const struct snd_kcontrol_new portaouten_ctl
=
1055 SOC_DAPM_SINGLE("Switch", CX2072X_PORTA_PIN_CTRL
, 6, 1, 0);
1057 static const struct snd_kcontrol_new porteouten_ctl
=
1058 SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL
, 6, 1, 0);
1060 static const struct snd_kcontrol_new portgouten_ctl
=
1061 SOC_DAPM_SINGLE("Switch", CX2072X_PORTG_PIN_CTRL
, 6, 1, 0);
1063 static const struct snd_kcontrol_new portmouten_ctl
=
1064 SOC_DAPM_SINGLE("Switch", CX2072X_PORTM_PIN_CTRL
, 6, 1, 0);
1066 static const struct snd_kcontrol_new portbinen_ctl
=
1067 SOC_DAPM_SINGLE("Switch", CX2072X_PORTB_PIN_CTRL
, 5, 1, 0);
1069 static const struct snd_kcontrol_new portcinen_ctl
=
1070 SOC_DAPM_SINGLE("Switch", CX2072X_PORTC_PIN_CTRL
, 5, 1, 0);
1072 static const struct snd_kcontrol_new portdinen_ctl
=
1073 SOC_DAPM_SINGLE("Switch", CX2072X_PORTD_PIN_CTRL
, 5, 1, 0);
1075 static const struct snd_kcontrol_new porteinen_ctl
=
1076 SOC_DAPM_SINGLE("Switch", CX2072X_PORTE_PIN_CTRL
, 5, 1, 0);
1078 static const struct snd_kcontrol_new i2sadc1l_ctl
=
1079 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2
, 0, 1, 0);
1081 static const struct snd_kcontrol_new i2sadc1r_ctl
=
1082 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2
, 1, 1, 0);
1084 static const struct snd_kcontrol_new i2sadc2l_ctl
=
1085 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2
, 2, 1, 0);
1087 static const struct snd_kcontrol_new i2sadc2r_ctl
=
1088 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL2
, 3, 1, 0);
1090 static const struct snd_kcontrol_new i2sdac1l_ctl
=
1091 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3
, 0, 1, 0);
1093 static const struct snd_kcontrol_new i2sdac1r_ctl
=
1094 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3
, 1, 1, 0);
1096 static const struct snd_kcontrol_new i2sdac2l_ctl
=
1097 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3
, 2, 1, 0);
1099 static const struct snd_kcontrol_new i2sdac2r_ctl
=
1100 SOC_DAPM_SINGLE("Switch", CX2072X_I2SPCM_CONTROL3
, 3, 1, 0);
1102 static const char * const dac_enum_text
[] = {
1103 "DAC1 Switch", "DAC2 Switch",
1106 static const struct soc_enum porta_dac_enum
=
1107 SOC_ENUM_SINGLE(CX2072X_PORTA_CONNECTION_SELECT_CTRL
, 0, 2, dac_enum_text
);
1109 static const struct snd_kcontrol_new porta_mux
=
1110 SOC_DAPM_ENUM("PortA Mux", porta_dac_enum
);
1112 static const struct soc_enum portg_dac_enum
=
1113 SOC_ENUM_SINGLE(CX2072X_PORTG_CONNECTION_SELECT_CTRL
, 0, 2, dac_enum_text
);
1115 static const struct snd_kcontrol_new portg_mux
=
1116 SOC_DAPM_ENUM("PortG Mux", portg_dac_enum
);
1118 static const struct soc_enum porte_dac_enum
=
1119 SOC_ENUM_SINGLE(CX2072X_PORTE_CONNECTION_SELECT_CTRL
, 0, 2, dac_enum_text
);
1121 static const struct snd_kcontrol_new porte_mux
=
1122 SOC_DAPM_ENUM("PortE Mux", porte_dac_enum
);
1124 static const struct soc_enum portm_dac_enum
=
1125 SOC_ENUM_SINGLE(CX2072X_PORTM_CONNECTION_SELECT_CTRL
, 0, 2, dac_enum_text
);
1127 static const struct snd_kcontrol_new portm_mux
=
1128 SOC_DAPM_ENUM("PortM Mux", portm_dac_enum
);
1130 static const char * const adc1in_sel_text
[] = {
1131 "PortB Switch", "PortD Switch", "PortC Switch", "Widget15 Switch",
1132 "PortE Switch", "PortF Switch", "PortH Switch"
1135 static const struct soc_enum adc1in_sel_enum
=
1136 SOC_ENUM_SINGLE(CX2072X_ADC1_CONNECTION_SELECT_CONTROL
, 0, 7, adc1in_sel_text
);
1138 static const struct snd_kcontrol_new adc1_mux
=
1139 SOC_DAPM_ENUM("ADC1 Mux", adc1in_sel_enum
);
1141 static const char * const adc2in_sel_text
[] = {
1142 "PortC Switch", "Widget15 Switch", "PortH Switch"
1145 static const struct soc_enum adc2in_sel_enum
=
1146 SOC_ENUM_SINGLE(CX2072X_ADC2_CONNECTION_SELECT_CONTROL
, 0, 3, adc2in_sel_text
);
1148 static const struct snd_kcontrol_new adc2_mux
=
1149 SOC_DAPM_ENUM("ADC2 Mux", adc2in_sel_enum
);
1151 static const struct snd_kcontrol_new wid15_mix
[] = {
1152 SOC_DAPM_SINGLE("DAC1L Switch", CX2072X_MIXER_GAIN_LEFT_0
, 7, 1, 1),
1153 SOC_DAPM_SINGLE("DAC1R Switch", CX2072X_MIXER_GAIN_RIGHT_0
, 7, 1, 1),
1154 SOC_DAPM_SINGLE("DAC2L Switch", CX2072X_MIXER_GAIN_LEFT_1
, 7, 1, 1),
1155 SOC_DAPM_SINGLE("DAC2R Switch", CX2072X_MIXER_GAIN_RIGHT_1
, 7, 1, 1),
1158 #define CX2072X_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, wmask, won_val, \
1159 woff_val, wevent, wflags) \
1160 {.id = snd_soc_dapm_supply, .name = wname, .kcontrol_news = NULL, \
1161 .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1162 .on_val = won_val, .off_val = woff_val, \
1163 .subseq = wsubseq, .event = wevent, .event_flags = wflags}
1165 #define CX2072X_DAPM_SWITCH(wname, wreg, wshift, wmask, won_val, woff_val, \
1167 {.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
1168 .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1169 .on_val = won_val, .off_val = woff_val, \
1170 .event = wevent, .event_flags = wflags}
1172 #define CX2072X_DAPM_SWITCH(wname, wreg, wshift, wmask, won_val, woff_val, \
1174 {.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
1175 .num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
1176 .on_val = won_val, .off_val = woff_val, \
1177 .event = wevent, .event_flags = wflags}
1179 #define CX2072X_DAPM_REG_E(wid, wname, wreg, wshift, wmask, won_val, woff_val, \
1181 {.id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
1182 .reg = wreg, .shift = wshift, .mask = wmask, \
1183 .on_val = won_val, .off_val = woff_val, \
1184 .event = wevent, .event_flags = wflags}
1186 static const struct snd_soc_dapm_widget cx2072x_dapm_widgets
[] = {
1188 SND_SOC_DAPM_AIF_IN("In AIF", "Playback", 0, SND_SOC_NOPM
, 0, 0),
1190 SND_SOC_DAPM_SWITCH("I2S DAC1L", SND_SOC_NOPM
, 0, 0, &i2sdac1l_ctl
),
1191 SND_SOC_DAPM_SWITCH("I2S DAC1R", SND_SOC_NOPM
, 0, 0, &i2sdac1r_ctl
),
1192 SND_SOC_DAPM_SWITCH("I2S DAC2L", SND_SOC_NOPM
, 0, 0, &i2sdac2l_ctl
),
1193 SND_SOC_DAPM_SWITCH("I2S DAC2R", SND_SOC_NOPM
, 0, 0, &i2sdac2r_ctl
),
1195 SND_SOC_DAPM_REG(snd_soc_dapm_dac
, "DAC1", CX2072X_DAC1_POWER_STATE
,
1196 0, 0xfff, 0x00, 0x03),
1198 SND_SOC_DAPM_REG(snd_soc_dapm_dac
, "DAC2", CX2072X_DAC2_POWER_STATE
,
1199 0, 0xfff, 0x00, 0x03),
1201 SND_SOC_DAPM_MUX("PortA Mux", SND_SOC_NOPM
, 0, 0, &porta_mux
),
1202 SND_SOC_DAPM_MUX("PortG Mux", SND_SOC_NOPM
, 0, 0, &portg_mux
),
1203 SND_SOC_DAPM_MUX("PortE Mux", SND_SOC_NOPM
, 0, 0, &porte_mux
),
1204 SND_SOC_DAPM_MUX("PortM Mux", SND_SOC_NOPM
, 0, 0, &portm_mux
),
1206 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortA Power",
1207 CX2072X_PORTA_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1209 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortM Power",
1210 CX2072X_PORTM_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1212 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortG Power",
1213 CX2072X_PORTG_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1215 CX2072X_DAPM_SUPPLY_S("AFG Power", 0, CX2072X_AFG_POWER_STATE
,
1216 0, 0xfff, 0x00, 0x03, afg_power_ev
,
1217 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_PRE_PMD
),
1219 SND_SOC_DAPM_SWITCH("PortA Out En", SND_SOC_NOPM
, 0, 0,
1221 SND_SOC_DAPM_SWITCH("PortE Out En", SND_SOC_NOPM
, 0, 0,
1223 SND_SOC_DAPM_SWITCH("PortG Out En", SND_SOC_NOPM
, 0, 0,
1225 SND_SOC_DAPM_SWITCH("PortM Out En", SND_SOC_NOPM
, 0, 0,
1228 SND_SOC_DAPM_OUTPUT("PORTA"),
1229 SND_SOC_DAPM_OUTPUT("PORTG"),
1230 SND_SOC_DAPM_OUTPUT("PORTE"),
1231 SND_SOC_DAPM_OUTPUT("PORTM"),
1232 SND_SOC_DAPM_OUTPUT("AEC REF"),
1235 SND_SOC_DAPM_AIF_OUT("Out AIF", "Capture", 0, SND_SOC_NOPM
, 0, 0),
1237 SND_SOC_DAPM_SWITCH("I2S ADC1L", SND_SOC_NOPM
, 0, 0, &i2sadc1l_ctl
),
1238 SND_SOC_DAPM_SWITCH("I2S ADC1R", SND_SOC_NOPM
, 0, 0, &i2sadc1r_ctl
),
1239 SND_SOC_DAPM_SWITCH("I2S ADC2L", SND_SOC_NOPM
, 0, 0, &i2sadc2l_ctl
),
1240 SND_SOC_DAPM_SWITCH("I2S ADC2R", SND_SOC_NOPM
, 0, 0, &i2sadc2r_ctl
),
1242 SND_SOC_DAPM_REG(snd_soc_dapm_adc
, "ADC1", CX2072X_ADC1_POWER_STATE
,
1243 0, 0xff, 0x00, 0x03),
1244 SND_SOC_DAPM_REG(snd_soc_dapm_adc
, "ADC2", CX2072X_ADC2_POWER_STATE
,
1245 0, 0xff, 0x00, 0x03),
1247 SND_SOC_DAPM_MUX("ADC1 Mux", SND_SOC_NOPM
, 0, 0, &adc1_mux
),
1248 SND_SOC_DAPM_MUX("ADC2 Mux", SND_SOC_NOPM
, 0, 0, &adc2_mux
),
1250 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortB Power",
1251 CX2072X_PORTB_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1252 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortC Power",
1253 CX2072X_PORTC_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1254 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortD Power",
1255 CX2072X_PORTD_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1256 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "PortE Power",
1257 CX2072X_PORTE_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1258 SND_SOC_DAPM_REG(snd_soc_dapm_supply
, "Widget15 Power",
1259 CX2072X_MIXER_POWER_STATE
, 0, 0xfff, 0x00, 0x03),
1261 SND_SOC_DAPM_MIXER("Widget15 Mixer", SND_SOC_NOPM
, 0, 0,
1262 wid15_mix
, ARRAY_SIZE(wid15_mix
)),
1263 SND_SOC_DAPM_SWITCH("PortB In En", SND_SOC_NOPM
, 0, 0, &portbinen_ctl
),
1264 SND_SOC_DAPM_SWITCH("PortC In En", SND_SOC_NOPM
, 0, 0, &portcinen_ctl
),
1265 SND_SOC_DAPM_SWITCH("PortD In En", SND_SOC_NOPM
, 0, 0, &portdinen_ctl
),
1266 SND_SOC_DAPM_SWITCH("PortE In En", SND_SOC_NOPM
, 0, 0, &porteinen_ctl
),
1268 SND_SOC_DAPM_MICBIAS("Headset Bias", CX2072X_ANALOG_TEST11
, 1, 0),
1269 SND_SOC_DAPM_MICBIAS("PortB Mic Bias", CX2072X_PORTB_PIN_CTRL
, 2, 0),
1270 SND_SOC_DAPM_MICBIAS("PortD Mic Bias", CX2072X_PORTD_PIN_CTRL
, 2, 0),
1271 SND_SOC_DAPM_MICBIAS("PortE Mic Bias", CX2072X_PORTE_PIN_CTRL
, 2, 0),
1272 SND_SOC_DAPM_INPUT("PORTB"),
1273 SND_SOC_DAPM_INPUT("PORTC"),
1274 SND_SOC_DAPM_INPUT("PORTD"),
1275 SND_SOC_DAPM_INPUT("PORTEIN"),
1279 static const struct snd_soc_dapm_route cx2072x_intercon
[] = {
1281 {"In AIF", NULL
, "AFG Power"},
1282 {"I2S DAC1L", "Switch", "In AIF"},
1283 {"I2S DAC1R", "Switch", "In AIF"},
1284 {"I2S DAC2L", "Switch", "In AIF"},
1285 {"I2S DAC2R", "Switch", "In AIF"},
1286 {"DAC1", NULL
, "I2S DAC1L"},
1287 {"DAC1", NULL
, "I2S DAC1R"},
1288 {"DAC2", NULL
, "I2S DAC2L"},
1289 {"DAC2", NULL
, "I2S DAC2R"},
1290 {"PortA Mux", "DAC1 Switch", "DAC1"},
1291 {"PortA Mux", "DAC2 Switch", "DAC2"},
1292 {"PortG Mux", "DAC1 Switch", "DAC1"},
1293 {"PortG Mux", "DAC2 Switch", "DAC2"},
1294 {"PortE Mux", "DAC1 Switch", "DAC1"},
1295 {"PortE Mux", "DAC2 Switch", "DAC2"},
1296 {"PortM Mux", "DAC1 Switch", "DAC1"},
1297 {"PortM Mux", "DAC2 Switch", "DAC2"},
1298 {"Widget15 Mixer", "DAC1L Switch", "DAC1"},
1299 {"Widget15 Mixer", "DAC1R Switch", "DAC2"},
1300 {"Widget15 Mixer", "DAC2L Switch", "DAC1"},
1301 {"Widget15 Mixer", "DAC2R Switch", "DAC2"},
1302 {"Widget15 Mixer", NULL
, "Widget15 Power"},
1303 {"PortA Out En", "Switch", "PortA Mux"},
1304 {"PortG Out En", "Switch", "PortG Mux"},
1305 {"PortE Out En", "Switch", "PortE Mux"},
1306 {"PortM Out En", "Switch", "PortM Mux"},
1307 {"PortA Mux", NULL
, "PortA Power"},
1308 {"PortG Mux", NULL
, "PortG Power"},
1309 {"PortE Mux", NULL
, "PortE Power"},
1310 {"PortM Mux", NULL
, "PortM Power"},
1311 {"PortA Out En", NULL
, "PortA Power"},
1312 {"PortG Out En", NULL
, "PortG Power"},
1313 {"PortE Out En", NULL
, "PortE Power"},
1314 {"PortM Out En", NULL
, "PortM Power"},
1315 {"PORTA", NULL
, "PortA Out En"},
1316 {"PORTG", NULL
, "PortG Out En"},
1317 {"PORTE", NULL
, "PortE Out En"},
1318 {"PORTM", NULL
, "PortM Out En"},
1321 {"PORTD", NULL
, "Headset Bias"},
1322 {"PortB In En", "Switch", "PORTB"},
1323 {"PortC In En", "Switch", "PORTC"},
1324 {"PortD In En", "Switch", "PORTD"},
1325 {"PortE In En", "Switch", "PORTEIN"},
1326 {"ADC1 Mux", "PortB Switch", "PortB In En"},
1327 {"ADC1 Mux", "PortC Switch", "PortC In En"},
1328 {"ADC1 Mux", "PortD Switch", "PortD In En"},
1329 {"ADC1 Mux", "PortE Switch", "PortE In En"},
1330 {"ADC1 Mux", "Widget15 Switch", "Widget15 Mixer"},
1331 {"ADC2 Mux", "PortC Switch", "PortC In En"},
1332 {"ADC2 Mux", "Widget15 Switch", "Widget15 Mixer"},
1333 {"ADC1", NULL
, "ADC1 Mux"},
1334 {"ADC2", NULL
, "ADC2 Mux"},
1335 {"I2S ADC1L", "Switch", "ADC1"},
1336 {"I2S ADC1R", "Switch", "ADC1"},
1337 {"I2S ADC2L", "Switch", "ADC2"},
1338 {"I2S ADC2R", "Switch", "ADC2"},
1339 {"Out AIF", NULL
, "I2S ADC1L"},
1340 {"Out AIF", NULL
, "I2S ADC1R"},
1341 {"Out AIF", NULL
, "I2S ADC2L"},
1342 {"Out AIF", NULL
, "I2S ADC2R"},
1343 {"Out AIF", NULL
, "AFG Power"},
1344 {"AEC REF", NULL
, "Out AIF"},
1345 {"PortB In En", NULL
, "PortB Power"},
1346 {"PortC In En", NULL
, "PortC Power"},
1347 {"PortD In En", NULL
, "PortD Power"},
1348 {"PortE In En", NULL
, "PortE Power"},
1351 static int cx2072x_set_bias_level(struct snd_soc_component
*codec
,
1352 enum snd_soc_bias_level level
)
1354 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1355 const enum snd_soc_bias_level old_level
=
1356 snd_soc_component_get_bias_level(codec
);
1358 if (level
== SND_SOC_BIAS_STANDBY
&& old_level
== SND_SOC_BIAS_OFF
)
1359 regmap_write(cx2072x
->regmap
, CX2072X_AFG_POWER_STATE
, 0);
1360 else if (level
== SND_SOC_BIAS_OFF
&& old_level
!= SND_SOC_BIAS_OFF
)
1361 regmap_write(cx2072x
->regmap
, CX2072X_AFG_POWER_STATE
, 3);
1367 * FIXME: the whole jack detection code below is pretty platform-specific;
1368 * it has lots of implicit assumptions about the pins, etc.
1369 * However, since we have no other code and reference, take this hard-coded
1370 * setup for now. Once when we have different platform implementations,
1371 * this needs to be rewritten in a more generic form, or moving into the
1374 static void cx2072x_enable_jack_detect(struct snd_soc_component
*codec
)
1376 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1377 struct snd_soc_dapm_context
*dapm
= snd_soc_component_get_dapm(codec
);
1379 /* No-sticky input type */
1380 regmap_write(cx2072x
->regmap
, CX2072X_GPIO_STICKY_MASK
, 0x1f);
1382 /* Use GPOI0 as interrupt pin */
1383 regmap_write(cx2072x
->regmap
, CX2072X_UM_INTERRUPT_CRTL_E
, 0x12 << 24);
1385 /* Enables unsolitited message on PortA */
1386 regmap_write(cx2072x
->regmap
, CX2072X_PORTA_UNSOLICITED_RESPONSE
, 0x80);
1388 /* support both nokia and apple headset set. Monitor time = 275 ms */
1389 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST15
, 0x73);
1391 /* Disable TIP detection */
1392 regmap_write(cx2072x
->regmap
, CX2072X_ANALOG_TEST12
, 0x300);
1394 /* Switch MusicD3Live pin to GPIO */
1395 regmap_write(cx2072x
->regmap
, CX2072X_DIGITAL_TEST1
, 0);
1397 snd_soc_dapm_mutex_lock(dapm
);
1399 snd_soc_dapm_force_enable_pin_unlocked(dapm
, "PORTD");
1400 snd_soc_dapm_force_enable_pin_unlocked(dapm
, "Headset Bias");
1401 snd_soc_dapm_force_enable_pin_unlocked(dapm
, "PortD Mic Bias");
1403 snd_soc_dapm_mutex_unlock(dapm
);
1406 static void cx2072x_disable_jack_detect(struct snd_soc_component
*codec
)
1408 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1410 regmap_write(cx2072x
->regmap
, CX2072X_UM_INTERRUPT_CRTL_E
, 0);
1411 regmap_write(cx2072x
->regmap
, CX2072X_PORTA_UNSOLICITED_RESPONSE
, 0);
1414 static int cx2072x_jack_status_check(void *data
)
1416 struct snd_soc_component
*codec
= data
;
1417 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1419 unsigned int type
= 0;
1422 mutex_lock(&cx2072x
->lock
);
1424 regmap_read(cx2072x
->regmap
, CX2072X_PORTA_PIN_SENSE
, &jack
);
1426 regmap_read(cx2072x
->regmap
, CX2072X_DIGITAL_TEST11
, &type
);
1433 state
|= SND_JACK_HEADSET
;
1435 state
|= SND_JACK_BTN_0
;
1436 } else if (type
& 0x4) {
1438 state
|= SND_JACK_HEADPHONE
;
1441 state
|= SND_JACK_HEADPHONE
;
1445 /* clear interrupt */
1446 regmap_write(cx2072x
->regmap
, CX2072X_UM_INTERRUPT_CRTL_E
, 0x12 << 24);
1448 mutex_unlock(&cx2072x
->lock
);
1450 dev_dbg(codec
->dev
, "CX2072X_HSDETECT type=0x%X,Jack state = %x\n",
1455 static const struct snd_soc_jack_gpio cx2072x_jack_gpio
= {
1457 .report
= SND_JACK_HEADSET
| SND_JACK_BTN_0
,
1458 .debounce_time
= 150,
1460 .jack_status_check
= cx2072x_jack_status_check
,
1463 static int cx2072x_set_jack(struct snd_soc_component
*codec
,
1464 struct snd_soc_jack
*jack
, void *data
)
1466 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1470 cx2072x_disable_jack_detect(codec
);
1474 if (!cx2072x
->jack_gpio
.gpiod_dev
) {
1475 cx2072x
->jack_gpio
= cx2072x_jack_gpio
;
1476 cx2072x
->jack_gpio
.gpiod_dev
= codec
->dev
;
1477 cx2072x
->jack_gpio
.data
= codec
;
1478 err
= snd_soc_jack_add_gpios(jack
, 1, &cx2072x
->jack_gpio
);
1480 cx2072x
->jack_gpio
.gpiod_dev
= NULL
;
1485 cx2072x_enable_jack_detect(codec
);
1489 static int cx2072x_probe(struct snd_soc_component
*codec
)
1491 struct cx2072x_priv
*cx2072x
= snd_soc_component_get_drvdata(codec
);
1493 cx2072x
->codec
= codec
;
1496 * FIXME: below is, again, a very platform-specific init sequence,
1497 * but we keep the code here just for simplicity. It seems that all
1498 * existing hardware implementations require this, so there is no very
1499 * much reason to move this out of the codec driver to the platform
1501 * But of course it's no "right" thing; if you are a good boy, don't
1502 * read and follow the code like this!
1504 pm_runtime_get_sync(codec
->dev
);
1505 regmap_write(cx2072x
->regmap
, CX2072X_AFG_POWER_STATE
, 0);
1507 regmap_multi_reg_write(cx2072x
->regmap
, cx2072x_reg_init
,
1508 ARRAY_SIZE(cx2072x_reg_init
));
1510 /* configure PortC as input device */
1511 regmap_update_bits(cx2072x
->regmap
, CX2072X_PORTC_PIN_CTRL
,
1514 regmap_update_bits(cx2072x
->regmap
, CX2072X_DIGITAL_BIOS_TEST2
,
1517 regmap_write(cx2072x
->regmap
, CX2072X_AFG_POWER_STATE
, 3);
1518 pm_runtime_put(codec
->dev
);
1523 static const struct snd_soc_component_driver soc_codec_driver_cx2072x
= {
1524 .probe
= cx2072x_probe
,
1525 .set_bias_level
= cx2072x_set_bias_level
,
1526 .set_jack
= cx2072x_set_jack
,
1527 .controls
= cx2072x_snd_controls
,
1528 .num_controls
= ARRAY_SIZE(cx2072x_snd_controls
),
1529 .dapm_widgets
= cx2072x_dapm_widgets
,
1530 .num_dapm_widgets
= ARRAY_SIZE(cx2072x_dapm_widgets
),
1531 .dapm_routes
= cx2072x_intercon
,
1532 .num_dapm_routes
= ARRAY_SIZE(cx2072x_intercon
),
1538 static struct snd_soc_dai_ops cx2072x_dai_ops
= {
1539 .set_sysclk
= cx2072x_set_dai_sysclk
,
1540 .set_fmt
= cx2072x_set_dai_fmt
,
1541 .hw_params
= cx2072x_hw_params
,
1542 .set_bclk_ratio
= cx2072x_set_dai_bclk_ratio
,
1545 static int cx2072x_dsp_dai_probe(struct snd_soc_dai
*dai
)
1547 struct cx2072x_priv
*cx2072x
=
1548 snd_soc_component_get_drvdata(dai
->component
);
1550 cx2072x
->en_aec_ref
= true;
1554 #define CX2072X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
1556 static struct snd_soc_dai_driver soc_codec_cx2072x_dai
[] = {
1557 { /* playback and capture */
1558 .name
= "cx2072x-hifi",
1559 .id
= CX2072X_DAI_HIFI
,
1561 .stream_name
= "Playback",
1564 .rates
= CX2072X_RATES_DSP
,
1565 .formats
= CX2072X_FORMATS
,
1568 .stream_name
= "Capture",
1571 .rates
= CX2072X_RATES_DSP
,
1572 .formats
= CX2072X_FORMATS
,
1574 .ops
= &cx2072x_dai_ops
,
1575 .symmetric_rates
= 1,
1577 { /* plabayck only, return echo reference to Conexant DSP chip */
1578 .name
= "cx2072x-dsp",
1579 .id
= CX2072X_DAI_DSP
,
1580 .probe
= cx2072x_dsp_dai_probe
,
1582 .stream_name
= "Playback",
1585 .rates
= CX2072X_RATES_DSP
,
1586 .formats
= CX2072X_FORMATS
,
1588 .ops
= &cx2072x_dai_ops
,
1590 { /* plabayck only, return echo reference through I2S TX */
1591 .name
= "cx2072x-aec",
1594 .stream_name
= "Capture",
1597 .rates
= CX2072X_RATES_DSP
,
1598 .formats
= CX2072X_FORMATS
,
1603 static const struct regmap_config cx2072x_regmap
= {
1606 .max_register
= CX2072X_REG_MAX
,
1607 .reg_defaults
= cx2072x_reg_defaults
,
1608 .num_reg_defaults
= ARRAY_SIZE(cx2072x_reg_defaults
),
1609 .cache_type
= REGCACHE_RBTREE
,
1610 .readable_reg
= cx2072x_readable_register
,
1611 .volatile_reg
= cx2072x_volatile_register
,
1612 /* Needs custom read/write functions for various register lengths */
1613 .reg_read
= cx2072x_reg_read
,
1614 .reg_write
= cx2072x_reg_write
,
1617 static int __maybe_unused
cx2072x_runtime_suspend(struct device
*dev
)
1619 struct cx2072x_priv
*cx2072x
= dev_get_drvdata(dev
);
1621 clk_disable_unprepare(cx2072x
->mclk
);
1625 static int __maybe_unused
cx2072x_runtime_resume(struct device
*dev
)
1627 struct cx2072x_priv
*cx2072x
= dev_get_drvdata(dev
);
1629 return clk_prepare_enable(cx2072x
->mclk
);
1632 static int cx2072x_i2c_probe(struct i2c_client
*i2c
,
1633 const struct i2c_device_id
*id
)
1635 struct cx2072x_priv
*cx2072x
;
1636 unsigned int ven_id
, rev_id
;
1639 cx2072x
= devm_kzalloc(&i2c
->dev
, sizeof(struct cx2072x_priv
),
1644 cx2072x
->regmap
= devm_regmap_init(&i2c
->dev
, NULL
, i2c
,
1646 if (IS_ERR(cx2072x
->regmap
))
1647 return PTR_ERR(cx2072x
->regmap
);
1649 mutex_init(&cx2072x
->lock
);
1651 i2c_set_clientdata(i2c
, cx2072x
);
1653 cx2072x
->dev
= &i2c
->dev
;
1654 cx2072x
->pll_changed
= true;
1655 cx2072x
->i2spcm_changed
= true;
1656 cx2072x
->bclk_ratio
= 0;
1658 cx2072x
->mclk
= devm_clk_get(cx2072x
->dev
, "mclk");
1659 if (IS_ERR(cx2072x
->mclk
)) {
1660 dev_err(cx2072x
->dev
, "Failed to get MCLK\n");
1661 return PTR_ERR(cx2072x
->mclk
);
1664 regmap_read(cx2072x
->regmap
, CX2072X_VENDOR_ID
, &ven_id
);
1665 regmap_read(cx2072x
->regmap
, CX2072X_REVISION_ID
, &rev_id
);
1667 dev_info(cx2072x
->dev
, "codec version: %08x,%08x\n", ven_id
, rev_id
);
1669 ret
= devm_snd_soc_register_component(cx2072x
->dev
,
1670 &soc_codec_driver_cx2072x
,
1671 soc_codec_cx2072x_dai
,
1672 ARRAY_SIZE(soc_codec_cx2072x_dai
));
1676 pm_runtime_use_autosuspend(cx2072x
->dev
);
1677 pm_runtime_enable(cx2072x
->dev
);
1682 static int cx2072x_i2c_remove(struct i2c_client
*i2c
)
1684 pm_runtime_disable(&i2c
->dev
);
1688 static const struct i2c_device_id cx2072x_i2c_id
[] = {
1693 MODULE_DEVICE_TABLE(i2c
, cx2072x_i2c_id
);
1696 static struct acpi_device_id cx2072x_acpi_match
[] = {
1700 MODULE_DEVICE_TABLE(acpi
, cx2072x_acpi_match
);
1703 static const struct dev_pm_ops cx2072x_runtime_pm
= {
1704 SET_RUNTIME_PM_OPS(cx2072x_runtime_suspend
, cx2072x_runtime_resume
,
1706 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1707 pm_runtime_force_resume
)
1710 static struct i2c_driver cx2072x_i2c_driver
= {
1713 .acpi_match_table
= ACPI_PTR(cx2072x_acpi_match
),
1714 .pm
= &cx2072x_runtime_pm
,
1716 .probe
= cx2072x_i2c_probe
,
1717 .remove
= cx2072x_i2c_remove
,
1718 .id_table
= cx2072x_i2c_id
,
1721 module_i2c_driver(cx2072x_i2c_driver
);
1723 MODULE_DESCRIPTION("ASoC cx2072x Codec Driver");
1724 MODULE_AUTHOR("Simon Ho <simon.ho@conexant.com>");
1725 MODULE_LICENSE("GPL");