1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * PCM3168A codec driver |
4 | * |
5 | * Copyright (C) 2015 Imagination Technologies Ltd. |
6 | * |
7 | * Author: Damien Horsley <Damien.Horsley@imgtec.com> |
8 | */ |
9 | |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/gpio/consumer.h> |
13 | #include <linux/module.h> |
14 | #include <linux/of_gpio.h> |
15 | #include <linux/pm_runtime.h> |
16 | #include <linux/regulator/consumer.h> |
17 | |
18 | #include <sound/pcm_params.h> |
19 | #include <sound/soc.h> |
20 | #include <sound/tlv.h> |
21 | |
22 | #include "pcm3168a.h" |
23 | |
24 | #define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
25 | SNDRV_PCM_FMTBIT_S24_3LE | \ |
26 | SNDRV_PCM_FMTBIT_S24_LE) |
27 | |
28 | #define PCM3168A_FMT_I2S 0x0 |
29 | #define PCM3168A_FMT_LEFT_J 0x1 |
30 | #define PCM3168A_FMT_RIGHT_J 0x2 |
31 | #define PCM3168A_FMT_RIGHT_J_16 0x3 |
32 | #define PCM3168A_FMT_DSP_A 0x4 |
33 | #define PCM3168A_FMT_DSP_B 0x5 |
34 | #define PCM3168A_FMT_I2S_TDM 0x6 |
35 | #define PCM3168A_FMT_LEFT_J_TDM 0x7 |
36 | |
37 | static const char *const pcm3168a_supply_names[] = { |
38 | "VDD1" , |
39 | "VDD2" , |
40 | "VCCAD1" , |
41 | "VCCAD2" , |
42 | "VCCDA1" , |
43 | "VCCDA2" |
44 | }; |
45 | |
46 | #define PCM3168A_DAI_DAC 0 |
47 | #define PCM3168A_DAI_ADC 1 |
48 | |
49 | /* ADC/DAC side parameters */ |
50 | struct pcm3168a_io_params { |
51 | bool provider_mode; |
52 | unsigned int format; |
53 | int tdm_slots; |
54 | u32 tdm_mask; |
55 | int slot_width; |
56 | }; |
57 | |
58 | struct pcm3168a_priv { |
59 | struct regulator_bulk_data supplies[ARRAY_SIZE(pcm3168a_supply_names)]; |
60 | struct regmap *regmap; |
61 | struct clk *scki; |
62 | struct gpio_desc *gpio_rst; |
63 | unsigned long sysclk; |
64 | |
65 | struct pcm3168a_io_params io_params[2]; |
66 | struct snd_soc_dai_driver dai_drv[2]; |
67 | }; |
68 | |
69 | static const char *const pcm3168a_roll_off[] = { "Sharp" , "Slow" }; |
70 | |
71 | static SOC_ENUM_SINGLE_DECL(pcm3168a_d1_roll_off, PCM3168A_DAC_OP_FLT, |
72 | PCM3168A_DAC_FLT_SHIFT, pcm3168a_roll_off); |
73 | static SOC_ENUM_SINGLE_DECL(pcm3168a_d2_roll_off, PCM3168A_DAC_OP_FLT, |
74 | PCM3168A_DAC_FLT_SHIFT + 1, pcm3168a_roll_off); |
75 | static SOC_ENUM_SINGLE_DECL(pcm3168a_d3_roll_off, PCM3168A_DAC_OP_FLT, |
76 | PCM3168A_DAC_FLT_SHIFT + 2, pcm3168a_roll_off); |
77 | static SOC_ENUM_SINGLE_DECL(pcm3168a_d4_roll_off, PCM3168A_DAC_OP_FLT, |
78 | PCM3168A_DAC_FLT_SHIFT + 3, pcm3168a_roll_off); |
79 | |
80 | static const char *const pcm3168a_volume_type[] = { |
81 | "Individual" , "Master + Individual" }; |
82 | |
83 | static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_volume_type, PCM3168A_DAC_ATT_DEMP_ZF, |
84 | PCM3168A_DAC_ATMDDA_SHIFT, pcm3168a_volume_type); |
85 | |
86 | static const char *const pcm3168a_att_speed_mult[] = { "2048" , "4096" }; |
87 | |
88 | static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_att_mult, PCM3168A_DAC_ATT_DEMP_ZF, |
89 | PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_att_speed_mult); |
90 | |
91 | static const char *const pcm3168a_demp[] = { |
92 | "Disabled" , "48khz" , "44.1khz" , "32khz" }; |
93 | |
94 | static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_demp, PCM3168A_DAC_ATT_DEMP_ZF, |
95 | PCM3168A_DAC_DEMP_SHIFT, pcm3168a_demp); |
96 | |
97 | static const char *const pcm3168a_zf_func[] = { |
98 | "DAC 1/2/3/4 AND" , "DAC 1/2/3/4 OR" , "DAC 1/2/3 AND" , |
99 | "DAC 1/2/3 OR" , "DAC 4 AND" , "DAC 4 OR" }; |
100 | |
101 | static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_func, PCM3168A_DAC_ATT_DEMP_ZF, |
102 | PCM3168A_DAC_AZRO_SHIFT, pcm3168a_zf_func); |
103 | |
104 | static const char *const pcm3168a_pol[] = { "Active High" , "Active Low" }; |
105 | |
106 | static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_pol, PCM3168A_DAC_ATT_DEMP_ZF, |
107 | PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_pol); |
108 | |
109 | static const char *const pcm3168a_con[] = { "Differential" , "Single-Ended" }; |
110 | |
111 | static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc1_con, PCM3168A_ADC_SEAD, |
112 | 0, 1, pcm3168a_con); |
113 | static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc2_con, PCM3168A_ADC_SEAD, |
114 | 2, 3, pcm3168a_con); |
115 | static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc3_con, PCM3168A_ADC_SEAD, |
116 | 4, 5, pcm3168a_con); |
117 | |
118 | static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_volume_type, PCM3168A_ADC_ATT_OVF, |
119 | PCM3168A_ADC_ATMDAD_SHIFT, pcm3168a_volume_type); |
120 | |
121 | static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_att_mult, PCM3168A_ADC_ATT_OVF, |
122 | PCM3168A_ADC_ATSPAD_SHIFT, pcm3168a_att_speed_mult); |
123 | |
124 | static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_ov_pol, PCM3168A_ADC_ATT_OVF, |
125 | PCM3168A_ADC_OVFP_SHIFT, pcm3168a_pol); |
126 | |
127 | /* -100db to 0db, register values 0-54 cause mute */ |
128 | static const DECLARE_TLV_DB_SCALE(pcm3168a_dac_tlv, -10050, 50, 1); |
129 | |
130 | /* -100db to 20db, register values 0-14 cause mute */ |
131 | static const DECLARE_TLV_DB_SCALE(pcm3168a_adc_tlv, -10050, 50, 1); |
132 | |
133 | static const struct snd_kcontrol_new pcm3168a_snd_controls[] = { |
134 | SOC_SINGLE("DAC Power-Save Switch" , PCM3168A_DAC_PWR_MST_FMT, |
135 | PCM3168A_DAC_PSMDA_SHIFT, 1, 1), |
136 | SOC_ENUM("DAC1 Digital Filter roll-off" , pcm3168a_d1_roll_off), |
137 | SOC_ENUM("DAC2 Digital Filter roll-off" , pcm3168a_d2_roll_off), |
138 | SOC_ENUM("DAC3 Digital Filter roll-off" , pcm3168a_d3_roll_off), |
139 | SOC_ENUM("DAC4 Digital Filter roll-off" , pcm3168a_d4_roll_off), |
140 | SOC_DOUBLE("DAC1 Invert Switch" , PCM3168A_DAC_INV, 0, 1, 1, 0), |
141 | SOC_DOUBLE("DAC2 Invert Switch" , PCM3168A_DAC_INV, 2, 3, 1, 0), |
142 | SOC_DOUBLE("DAC3 Invert Switch" , PCM3168A_DAC_INV, 4, 5, 1, 0), |
143 | SOC_DOUBLE("DAC4 Invert Switch" , PCM3168A_DAC_INV, 6, 7, 1, 0), |
144 | SOC_ENUM("DAC Volume Control Type" , pcm3168a_dac_volume_type), |
145 | SOC_ENUM("DAC Volume Rate Multiplier" , pcm3168a_dac_att_mult), |
146 | SOC_ENUM("DAC De-Emphasis" , pcm3168a_dac_demp), |
147 | SOC_ENUM("DAC Zero Flag Function" , pcm3168a_dac_zf_func), |
148 | SOC_ENUM("DAC Zero Flag Polarity" , pcm3168a_dac_zf_pol), |
149 | SOC_SINGLE_RANGE_TLV("Master Playback Volume" , |
150 | PCM3168A_DAC_VOL_MASTER, 0, 54, 255, 0, |
151 | pcm3168a_dac_tlv), |
152 | SOC_DOUBLE_R_RANGE_TLV("DAC1 Playback Volume" , |
153 | PCM3168A_DAC_VOL_CHAN_START, |
154 | PCM3168A_DAC_VOL_CHAN_START + 1, |
155 | 0, 54, 255, 0, pcm3168a_dac_tlv), |
156 | SOC_DOUBLE_R_RANGE_TLV("DAC2 Playback Volume" , |
157 | PCM3168A_DAC_VOL_CHAN_START + 2, |
158 | PCM3168A_DAC_VOL_CHAN_START + 3, |
159 | 0, 54, 255, 0, pcm3168a_dac_tlv), |
160 | SOC_DOUBLE_R_RANGE_TLV("DAC3 Playback Volume" , |
161 | PCM3168A_DAC_VOL_CHAN_START + 4, |
162 | PCM3168A_DAC_VOL_CHAN_START + 5, |
163 | 0, 54, 255, 0, pcm3168a_dac_tlv), |
164 | SOC_DOUBLE_R_RANGE_TLV("DAC4 Playback Volume" , |
165 | PCM3168A_DAC_VOL_CHAN_START + 6, |
166 | PCM3168A_DAC_VOL_CHAN_START + 7, |
167 | 0, 54, 255, 0, pcm3168a_dac_tlv), |
168 | SOC_SINGLE("ADC1 High-Pass Filter Switch" , PCM3168A_ADC_PWR_HPFB, |
169 | PCM3168A_ADC_BYP_SHIFT, 1, 1), |
170 | SOC_SINGLE("ADC2 High-Pass Filter Switch" , PCM3168A_ADC_PWR_HPFB, |
171 | PCM3168A_ADC_BYP_SHIFT + 1, 1, 1), |
172 | SOC_SINGLE("ADC3 High-Pass Filter Switch" , PCM3168A_ADC_PWR_HPFB, |
173 | PCM3168A_ADC_BYP_SHIFT + 2, 1, 1), |
174 | SOC_ENUM("ADC1 Connection Type" , pcm3168a_adc1_con), |
175 | SOC_ENUM("ADC2 Connection Type" , pcm3168a_adc2_con), |
176 | SOC_ENUM("ADC3 Connection Type" , pcm3168a_adc3_con), |
177 | SOC_DOUBLE("ADC1 Invert Switch" , PCM3168A_ADC_INV, 0, 1, 1, 0), |
178 | SOC_DOUBLE("ADC2 Invert Switch" , PCM3168A_ADC_INV, 2, 3, 1, 0), |
179 | SOC_DOUBLE("ADC3 Invert Switch" , PCM3168A_ADC_INV, 4, 5, 1, 0), |
180 | SOC_DOUBLE("ADC1 Mute Switch" , PCM3168A_ADC_MUTE, 0, 1, 1, 0), |
181 | SOC_DOUBLE("ADC2 Mute Switch" , PCM3168A_ADC_MUTE, 2, 3, 1, 0), |
182 | SOC_DOUBLE("ADC3 Mute Switch" , PCM3168A_ADC_MUTE, 4, 5, 1, 0), |
183 | SOC_ENUM("ADC Volume Control Type" , pcm3168a_adc_volume_type), |
184 | SOC_ENUM("ADC Volume Rate Multiplier" , pcm3168a_adc_att_mult), |
185 | SOC_ENUM("ADC Overflow Flag Polarity" , pcm3168a_adc_ov_pol), |
186 | SOC_SINGLE_RANGE_TLV("Master Capture Volume" , |
187 | PCM3168A_ADC_VOL_MASTER, 0, 14, 255, 0, |
188 | pcm3168a_adc_tlv), |
189 | SOC_DOUBLE_R_RANGE_TLV("ADC1 Capture Volume" , |
190 | PCM3168A_ADC_VOL_CHAN_START, |
191 | PCM3168A_ADC_VOL_CHAN_START + 1, |
192 | 0, 14, 255, 0, pcm3168a_adc_tlv), |
193 | SOC_DOUBLE_R_RANGE_TLV("ADC2 Capture Volume" , |
194 | PCM3168A_ADC_VOL_CHAN_START + 2, |
195 | PCM3168A_ADC_VOL_CHAN_START + 3, |
196 | 0, 14, 255, 0, pcm3168a_adc_tlv), |
197 | SOC_DOUBLE_R_RANGE_TLV("ADC3 Capture Volume" , |
198 | PCM3168A_ADC_VOL_CHAN_START + 4, |
199 | PCM3168A_ADC_VOL_CHAN_START + 5, |
200 | 0, 14, 255, 0, pcm3168a_adc_tlv) |
201 | }; |
202 | |
203 | static const struct snd_soc_dapm_widget pcm3168a_dapm_widgets[] = { |
204 | SND_SOC_DAPM_DAC("DAC1" , "Playback" , PCM3168A_DAC_OP_FLT, |
205 | PCM3168A_DAC_OPEDA_SHIFT, 1), |
206 | SND_SOC_DAPM_DAC("DAC2" , "Playback" , PCM3168A_DAC_OP_FLT, |
207 | PCM3168A_DAC_OPEDA_SHIFT + 1, 1), |
208 | SND_SOC_DAPM_DAC("DAC3" , "Playback" , PCM3168A_DAC_OP_FLT, |
209 | PCM3168A_DAC_OPEDA_SHIFT + 2, 1), |
210 | SND_SOC_DAPM_DAC("DAC4" , "Playback" , PCM3168A_DAC_OP_FLT, |
211 | PCM3168A_DAC_OPEDA_SHIFT + 3, 1), |
212 | |
213 | SND_SOC_DAPM_OUTPUT("AOUT1L" ), |
214 | SND_SOC_DAPM_OUTPUT("AOUT1R" ), |
215 | SND_SOC_DAPM_OUTPUT("AOUT2L" ), |
216 | SND_SOC_DAPM_OUTPUT("AOUT2R" ), |
217 | SND_SOC_DAPM_OUTPUT("AOUT3L" ), |
218 | SND_SOC_DAPM_OUTPUT("AOUT3R" ), |
219 | SND_SOC_DAPM_OUTPUT("AOUT4L" ), |
220 | SND_SOC_DAPM_OUTPUT("AOUT4R" ), |
221 | |
222 | SND_SOC_DAPM_ADC("ADC1" , "Capture" , PCM3168A_ADC_PWR_HPFB, |
223 | PCM3168A_ADC_PSVAD_SHIFT, 1), |
224 | SND_SOC_DAPM_ADC("ADC2" , "Capture" , PCM3168A_ADC_PWR_HPFB, |
225 | PCM3168A_ADC_PSVAD_SHIFT + 1, 1), |
226 | SND_SOC_DAPM_ADC("ADC3" , "Capture" , PCM3168A_ADC_PWR_HPFB, |
227 | PCM3168A_ADC_PSVAD_SHIFT + 2, 1), |
228 | |
229 | SND_SOC_DAPM_INPUT("AIN1L" ), |
230 | SND_SOC_DAPM_INPUT("AIN1R" ), |
231 | SND_SOC_DAPM_INPUT("AIN2L" ), |
232 | SND_SOC_DAPM_INPUT("AIN2R" ), |
233 | SND_SOC_DAPM_INPUT("AIN3L" ), |
234 | SND_SOC_DAPM_INPUT("AIN3R" ) |
235 | }; |
236 | |
237 | static const struct snd_soc_dapm_route pcm3168a_dapm_routes[] = { |
238 | /* Playback */ |
239 | { "AOUT1L" , NULL, "DAC1" }, |
240 | { "AOUT1R" , NULL, "DAC1" }, |
241 | |
242 | { "AOUT2L" , NULL, "DAC2" }, |
243 | { "AOUT2R" , NULL, "DAC2" }, |
244 | |
245 | { "AOUT3L" , NULL, "DAC3" }, |
246 | { "AOUT3R" , NULL, "DAC3" }, |
247 | |
248 | { "AOUT4L" , NULL, "DAC4" }, |
249 | { "AOUT4R" , NULL, "DAC4" }, |
250 | |
251 | /* Capture */ |
252 | { "ADC1" , NULL, "AIN1L" }, |
253 | { "ADC1" , NULL, "AIN1R" }, |
254 | |
255 | { "ADC2" , NULL, "AIN2L" }, |
256 | { "ADC2" , NULL, "AIN2R" }, |
257 | |
258 | { "ADC3" , NULL, "AIN3L" }, |
259 | { "ADC3" , NULL, "AIN3R" } |
260 | }; |
261 | |
262 | static unsigned int pcm3168a_scki_ratios[] = { |
263 | 768, |
264 | 512, |
265 | 384, |
266 | 256, |
267 | 192, |
268 | 128 |
269 | }; |
270 | |
271 | #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) |
272 | #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) |
273 | |
274 | #define PCM3168A_MAX_SYSCLK 36864000 |
275 | |
276 | static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) |
277 | { |
278 | int ret; |
279 | |
280 | ret = regmap_write(map: pcm3168a->regmap, PCM3168A_RST_SMODE, val: 0); |
281 | if (ret) |
282 | return ret; |
283 | |
284 | /* Internal reset is de-asserted after 3846 SCKI cycles */ |
285 | msleep(DIV_ROUND_UP(3846 * 1000, pcm3168a->sysclk)); |
286 | |
287 | return regmap_write(map: pcm3168a->regmap, PCM3168A_RST_SMODE, |
288 | PCM3168A_MRST_MASK | PCM3168A_SRST_MASK); |
289 | } |
290 | |
291 | static int pcm3168a_mute(struct snd_soc_dai *dai, int mute, int direction) |
292 | { |
293 | struct snd_soc_component *component = dai->component; |
294 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: component); |
295 | |
296 | regmap_write(map: pcm3168a->regmap, PCM3168A_DAC_MUTE, val: mute ? 0xff : 0); |
297 | |
298 | return 0; |
299 | } |
300 | |
301 | static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, |
302 | int clk_id, unsigned int freq, int dir) |
303 | { |
304 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: dai->component); |
305 | int ret; |
306 | |
307 | /* |
308 | * Some sound card sets 0 Hz as reset, |
309 | * but it is impossible to set. Ignore it here |
310 | */ |
311 | if (freq == 0) |
312 | return 0; |
313 | |
314 | if (freq > PCM3168A_MAX_SYSCLK) |
315 | return -EINVAL; |
316 | |
317 | ret = clk_set_rate(clk: pcm3168a->scki, rate: freq); |
318 | if (ret) |
319 | return ret; |
320 | |
321 | pcm3168a->sysclk = freq; |
322 | |
323 | return 0; |
324 | } |
325 | |
326 | static void pcm3168a_update_fixup_pcm_stream(struct snd_soc_dai *dai) |
327 | { |
328 | struct snd_soc_component *component = dai->component; |
329 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: component); |
330 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
331 | u64 formats = SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE; |
332 | unsigned int channel_max = dai->id == PCM3168A_DAI_DAC ? 8 : 6; |
333 | |
334 | if (io_params->format == SND_SOC_DAIFMT_RIGHT_J) { |
335 | /* S16_LE is only supported in RIGHT_J mode */ |
336 | formats |= SNDRV_PCM_FMTBIT_S16_LE; |
337 | |
338 | /* |
339 | * If multi DIN/DOUT is not selected, RIGHT_J can only support |
340 | * two channels (no TDM support) |
341 | */ |
342 | if (io_params->tdm_slots != 2) |
343 | channel_max = 2; |
344 | } |
345 | |
346 | if (dai->id == PCM3168A_DAI_DAC) { |
347 | dai->driver->playback.channels_max = channel_max; |
348 | dai->driver->playback.formats = formats; |
349 | } else { |
350 | dai->driver->capture.channels_max = channel_max; |
351 | dai->driver->capture.formats = formats; |
352 | } |
353 | } |
354 | |
355 | static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) |
356 | { |
357 | struct snd_soc_component *component = dai->component; |
358 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: component); |
359 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
360 | bool provider_mode; |
361 | |
362 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { |
363 | case SND_SOC_DAIFMT_LEFT_J: |
364 | case SND_SOC_DAIFMT_I2S: |
365 | case SND_SOC_DAIFMT_RIGHT_J: |
366 | case SND_SOC_DAIFMT_DSP_A: |
367 | case SND_SOC_DAIFMT_DSP_B: |
368 | break; |
369 | default: |
370 | dev_err(component->dev, "unsupported dai format\n" ); |
371 | return -EINVAL; |
372 | } |
373 | |
374 | switch (format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
375 | case SND_SOC_DAIFMT_CBC_CFC: |
376 | provider_mode = false; |
377 | break; |
378 | case SND_SOC_DAIFMT_CBP_CFP: |
379 | provider_mode = true; |
380 | break; |
381 | default: |
382 | dev_err(component->dev, "unsupported provider mode\n" ); |
383 | return -EINVAL; |
384 | } |
385 | |
386 | switch (format & SND_SOC_DAIFMT_INV_MASK) { |
387 | case SND_SOC_DAIFMT_NB_NF: |
388 | break; |
389 | default: |
390 | return -EINVAL; |
391 | } |
392 | |
393 | io_params->provider_mode = provider_mode; |
394 | io_params->format = format & SND_SOC_DAIFMT_FORMAT_MASK; |
395 | |
396 | pcm3168a_update_fixup_pcm_stream(dai); |
397 | |
398 | return 0; |
399 | } |
400 | |
401 | static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
402 | unsigned int rx_mask, int slots, |
403 | int slot_width) |
404 | { |
405 | struct snd_soc_component *component = dai->component; |
406 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: component); |
407 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
408 | |
409 | if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { |
410 | dev_err(component->dev, |
411 | "Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n" , |
412 | tx_mask, rx_mask, slots); |
413 | return -EINVAL; |
414 | } |
415 | |
416 | if (slot_width && |
417 | (slot_width != 16 && slot_width != 24 && slot_width != 32 )) { |
418 | dev_err(component->dev, "Unsupported slot_width %d\n" , |
419 | slot_width); |
420 | return -EINVAL; |
421 | } |
422 | |
423 | io_params->tdm_slots = slots; |
424 | io_params->slot_width = slot_width; |
425 | /* Ignore the not relevant mask for the DAI/direction */ |
426 | if (dai->id == PCM3168A_DAI_DAC) |
427 | io_params->tdm_mask = tx_mask; |
428 | else |
429 | io_params->tdm_mask = rx_mask; |
430 | |
431 | pcm3168a_update_fixup_pcm_stream(dai); |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static int pcm3168a_hw_params(struct snd_pcm_substream *substream, |
437 | struct snd_pcm_hw_params *params, |
438 | struct snd_soc_dai *dai) |
439 | { |
440 | struct snd_soc_component *component = dai->component; |
441 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(c: component); |
442 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
443 | bool provider_mode, tdm_mode; |
444 | unsigned int format; |
445 | unsigned int reg, mask, ms, ms_shift, fmt, fmt_shift, ratio, tdm_slots; |
446 | int i, num_scki_ratios, slot_width; |
447 | |
448 | if (dai->id == PCM3168A_DAI_DAC) { |
449 | num_scki_ratios = PCM3168A_NUM_SCKI_RATIOS_DAC; |
450 | reg = PCM3168A_DAC_PWR_MST_FMT; |
451 | mask = PCM3168A_DAC_MSDA_MASK | PCM3168A_DAC_FMT_MASK; |
452 | ms_shift = PCM3168A_DAC_MSDA_SHIFT; |
453 | fmt_shift = PCM3168A_DAC_FMT_SHIFT; |
454 | } else { |
455 | num_scki_ratios = PCM3168A_NUM_SCKI_RATIOS_ADC; |
456 | reg = PCM3168A_ADC_MST_FMT; |
457 | mask = PCM3168A_ADC_MSAD_MASK | PCM3168A_ADC_FMTAD_MASK; |
458 | ms_shift = PCM3168A_ADC_MSAD_SHIFT; |
459 | fmt_shift = PCM3168A_ADC_FMTAD_SHIFT; |
460 | } |
461 | |
462 | provider_mode = io_params->provider_mode; |
463 | |
464 | if (provider_mode) { |
465 | ratio = pcm3168a->sysclk / params_rate(p: params); |
466 | |
467 | for (i = 0; i < num_scki_ratios; i++) { |
468 | if (pcm3168a_scki_ratios[i] == ratio) |
469 | break; |
470 | } |
471 | |
472 | if (i == num_scki_ratios) { |
473 | dev_err(component->dev, "unsupported sysclk ratio\n" ); |
474 | return -EINVAL; |
475 | } |
476 | |
477 | ms = (i + 1); |
478 | } else { |
479 | ms = 0; |
480 | } |
481 | |
482 | format = io_params->format; |
483 | |
484 | if (io_params->slot_width) |
485 | slot_width = io_params->slot_width; |
486 | else |
487 | slot_width = params_width(p: params); |
488 | |
489 | switch (slot_width) { |
490 | case 16: |
491 | if (provider_mode || (format != SND_SOC_DAIFMT_RIGHT_J)) { |
492 | dev_err(component->dev, "16-bit slots are supported only for consumer mode using right justified\n" ); |
493 | return -EINVAL; |
494 | } |
495 | break; |
496 | case 24: |
497 | if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) || |
498 | (format == SND_SOC_DAIFMT_DSP_B)) { |
499 | dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n" ); |
500 | return -EINVAL; |
501 | } |
502 | break; |
503 | case 32: |
504 | break; |
505 | default: |
506 | dev_err(component->dev, "unsupported frame size: %d\n" , slot_width); |
507 | return -EINVAL; |
508 | } |
509 | |
510 | if (io_params->tdm_slots) |
511 | tdm_slots = io_params->tdm_slots; |
512 | else |
513 | tdm_slots = params_channels(p: params); |
514 | |
515 | /* |
516 | * Switch the codec to TDM mode when more than 2 TDM slots are needed |
517 | * for the stream. |
518 | * If pcm3168a->tdm_slots is not set or set to more than 2 (8/6 usually) |
519 | * then DIN1/DOUT1 is used in TDM mode. |
520 | * If pcm3168a->tdm_slots is set to 2 then DIN1/2/3/4 and DOUT1/2/3 is |
521 | * used in normal mode, no need to switch to TDM modes. |
522 | */ |
523 | tdm_mode = (tdm_slots > 2); |
524 | |
525 | if (tdm_mode) { |
526 | switch (format) { |
527 | case SND_SOC_DAIFMT_I2S: |
528 | case SND_SOC_DAIFMT_DSP_A: |
529 | case SND_SOC_DAIFMT_LEFT_J: |
530 | case SND_SOC_DAIFMT_DSP_B: |
531 | break; |
532 | default: |
533 | dev_err(component->dev, |
534 | "TDM is supported under DSP/I2S/Left_J only\n" ); |
535 | return -EINVAL; |
536 | } |
537 | } |
538 | |
539 | switch (format) { |
540 | case SND_SOC_DAIFMT_I2S: |
541 | fmt = tdm_mode ? PCM3168A_FMT_I2S_TDM : PCM3168A_FMT_I2S; |
542 | break; |
543 | case SND_SOC_DAIFMT_LEFT_J: |
544 | fmt = tdm_mode ? PCM3168A_FMT_LEFT_J_TDM : PCM3168A_FMT_LEFT_J; |
545 | break; |
546 | case SND_SOC_DAIFMT_RIGHT_J: |
547 | fmt = (slot_width == 16) ? PCM3168A_FMT_RIGHT_J_16 : |
548 | PCM3168A_FMT_RIGHT_J; |
549 | break; |
550 | case SND_SOC_DAIFMT_DSP_A: |
551 | fmt = tdm_mode ? PCM3168A_FMT_I2S_TDM : PCM3168A_FMT_DSP_A; |
552 | break; |
553 | case SND_SOC_DAIFMT_DSP_B: |
554 | fmt = tdm_mode ? PCM3168A_FMT_LEFT_J_TDM : PCM3168A_FMT_DSP_B; |
555 | break; |
556 | default: |
557 | return -EINVAL; |
558 | } |
559 | |
560 | regmap_update_bits(map: pcm3168a->regmap, reg, mask, |
561 | val: (ms << ms_shift) | (fmt << fmt_shift)); |
562 | |
563 | return 0; |
564 | } |
565 | |
566 | static u64 pcm3168a_dai_formats[] = { |
567 | /* |
568 | * Select below from Sound Card, not here |
569 | * SND_SOC_DAIFMT_CBC_CFC |
570 | * SND_SOC_DAIFMT_CBP_CFP |
571 | */ |
572 | |
573 | /* |
574 | * First Priority |
575 | */ |
576 | SND_SOC_POSSIBLE_DAIFMT_I2S | |
577 | SND_SOC_POSSIBLE_DAIFMT_LEFT_J, |
578 | /* |
579 | * Second Priority |
580 | * |
581 | * These have picky limitation. |
582 | * see |
583 | * pcm3168a_hw_params() |
584 | */ |
585 | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | |
586 | SND_SOC_POSSIBLE_DAIFMT_DSP_A | |
587 | SND_SOC_POSSIBLE_DAIFMT_DSP_B, |
588 | }; |
589 | |
590 | static const struct snd_soc_dai_ops pcm3168a_dai_ops = { |
591 | .set_fmt = pcm3168a_set_dai_fmt, |
592 | .set_sysclk = pcm3168a_set_dai_sysclk, |
593 | .hw_params = pcm3168a_hw_params, |
594 | .mute_stream = pcm3168a_mute, |
595 | .set_tdm_slot = pcm3168a_set_tdm_slot, |
596 | .no_capture_mute = 1, |
597 | .auto_selectable_formats = pcm3168a_dai_formats, |
598 | .num_auto_selectable_formats = ARRAY_SIZE(pcm3168a_dai_formats), |
599 | }; |
600 | |
601 | static struct snd_soc_dai_driver pcm3168a_dais[] = { |
602 | { |
603 | .name = "pcm3168a-dac" , |
604 | .id = PCM3168A_DAI_DAC, |
605 | .playback = { |
606 | .stream_name = "Playback" , |
607 | .channels_min = 1, |
608 | .channels_max = 8, |
609 | .rates = SNDRV_PCM_RATE_8000_192000, |
610 | .formats = PCM3168A_FORMATS |
611 | }, |
612 | .ops = &pcm3168a_dai_ops |
613 | }, |
614 | { |
615 | .name = "pcm3168a-adc" , |
616 | .id = PCM3168A_DAI_ADC, |
617 | .capture = { |
618 | .stream_name = "Capture" , |
619 | .channels_min = 1, |
620 | .channels_max = 6, |
621 | .rates = SNDRV_PCM_RATE_8000_96000, |
622 | .formats = PCM3168A_FORMATS |
623 | }, |
624 | .ops = &pcm3168a_dai_ops |
625 | }, |
626 | }; |
627 | |
628 | static const struct reg_default pcm3168a_reg_default[] = { |
629 | { PCM3168A_RST_SMODE, PCM3168A_MRST_MASK | PCM3168A_SRST_MASK }, |
630 | { PCM3168A_DAC_PWR_MST_FMT, 0x00 }, |
631 | { PCM3168A_DAC_OP_FLT, 0x00 }, |
632 | { PCM3168A_DAC_INV, 0x00 }, |
633 | { PCM3168A_DAC_MUTE, 0x00 }, |
634 | { PCM3168A_DAC_ZERO, 0x00 }, |
635 | { PCM3168A_DAC_ATT_DEMP_ZF, 0x00 }, |
636 | { PCM3168A_DAC_VOL_MASTER, 0xff }, |
637 | { PCM3168A_DAC_VOL_CHAN_START, 0xff }, |
638 | { PCM3168A_DAC_VOL_CHAN_START + 1, 0xff }, |
639 | { PCM3168A_DAC_VOL_CHAN_START + 2, 0xff }, |
640 | { PCM3168A_DAC_VOL_CHAN_START + 3, 0xff }, |
641 | { PCM3168A_DAC_VOL_CHAN_START + 4, 0xff }, |
642 | { PCM3168A_DAC_VOL_CHAN_START + 5, 0xff }, |
643 | { PCM3168A_DAC_VOL_CHAN_START + 6, 0xff }, |
644 | { PCM3168A_DAC_VOL_CHAN_START + 7, 0xff }, |
645 | { PCM3168A_ADC_SMODE, 0x00 }, |
646 | { PCM3168A_ADC_MST_FMT, 0x00 }, |
647 | { PCM3168A_ADC_PWR_HPFB, 0x00 }, |
648 | { PCM3168A_ADC_SEAD, 0x00 }, |
649 | { PCM3168A_ADC_INV, 0x00 }, |
650 | { PCM3168A_ADC_MUTE, 0x00 }, |
651 | { PCM3168A_ADC_OV, 0x00 }, |
652 | { PCM3168A_ADC_ATT_OVF, 0x00 }, |
653 | { PCM3168A_ADC_VOL_MASTER, 0xd3 }, |
654 | { PCM3168A_ADC_VOL_CHAN_START, 0xd3 }, |
655 | { PCM3168A_ADC_VOL_CHAN_START + 1, 0xd3 }, |
656 | { PCM3168A_ADC_VOL_CHAN_START + 2, 0xd3 }, |
657 | { PCM3168A_ADC_VOL_CHAN_START + 3, 0xd3 }, |
658 | { PCM3168A_ADC_VOL_CHAN_START + 4, 0xd3 }, |
659 | { PCM3168A_ADC_VOL_CHAN_START + 5, 0xd3 } |
660 | }; |
661 | |
662 | static bool pcm3168a_readable_register(struct device *dev, unsigned int reg) |
663 | { |
664 | if (reg >= PCM3168A_RST_SMODE) |
665 | return true; |
666 | else |
667 | return false; |
668 | } |
669 | |
670 | static bool pcm3168a_volatile_register(struct device *dev, unsigned int reg) |
671 | { |
672 | switch (reg) { |
673 | case PCM3168A_RST_SMODE: |
674 | case PCM3168A_DAC_ZERO: |
675 | case PCM3168A_ADC_OV: |
676 | return true; |
677 | default: |
678 | return false; |
679 | } |
680 | } |
681 | |
682 | static bool pcm3168a_writeable_register(struct device *dev, unsigned int reg) |
683 | { |
684 | if (reg < PCM3168A_RST_SMODE) |
685 | return false; |
686 | |
687 | switch (reg) { |
688 | case PCM3168A_DAC_ZERO: |
689 | case PCM3168A_ADC_OV: |
690 | return false; |
691 | default: |
692 | return true; |
693 | } |
694 | } |
695 | |
696 | const struct regmap_config pcm3168a_regmap = { |
697 | .reg_bits = 8, |
698 | .val_bits = 8, |
699 | |
700 | .max_register = PCM3168A_ADC_VOL_CHAN_START + 5, |
701 | .reg_defaults = pcm3168a_reg_default, |
702 | .num_reg_defaults = ARRAY_SIZE(pcm3168a_reg_default), |
703 | .readable_reg = pcm3168a_readable_register, |
704 | .volatile_reg = pcm3168a_volatile_register, |
705 | .writeable_reg = pcm3168a_writeable_register, |
706 | .cache_type = REGCACHE_FLAT |
707 | }; |
708 | EXPORT_SYMBOL_GPL(pcm3168a_regmap); |
709 | |
710 | static const struct snd_soc_component_driver pcm3168a_driver = { |
711 | .controls = pcm3168a_snd_controls, |
712 | .num_controls = ARRAY_SIZE(pcm3168a_snd_controls), |
713 | .dapm_widgets = pcm3168a_dapm_widgets, |
714 | .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets), |
715 | .dapm_routes = pcm3168a_dapm_routes, |
716 | .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes), |
717 | .use_pmdown_time = 1, |
718 | .endianness = 1, |
719 | }; |
720 | |
721 | int pcm3168a_probe(struct device *dev, struct regmap *regmap) |
722 | { |
723 | struct pcm3168a_priv *pcm3168a; |
724 | int ret, i; |
725 | |
726 | pcm3168a = devm_kzalloc(dev, size: sizeof(*pcm3168a), GFP_KERNEL); |
727 | if (pcm3168a == NULL) |
728 | return -ENOMEM; |
729 | |
730 | dev_set_drvdata(dev, data: pcm3168a); |
731 | |
732 | /* |
733 | * Request the reset (connected to RST pin) gpio line as non exclusive |
734 | * as the same reset line might be connected to multiple pcm3168a codec |
735 | * |
736 | * The RST is low active, we want the GPIO line to be high initially, so |
737 | * request the initial level to LOW which in practice means DEASSERTED: |
738 | * The deasserted level of GPIO_ACTIVE_LOW is HIGH. |
739 | */ |
740 | pcm3168a->gpio_rst = devm_gpiod_get_optional(dev, con_id: "reset" , |
741 | flags: GPIOD_OUT_LOW | |
742 | GPIOD_FLAGS_BIT_NONEXCLUSIVE); |
743 | if (IS_ERR(ptr: pcm3168a->gpio_rst)) |
744 | return dev_err_probe(dev, err: PTR_ERR(ptr: pcm3168a->gpio_rst), |
745 | fmt: "failed to acquire RST gpio\n" ); |
746 | |
747 | pcm3168a->scki = devm_clk_get(dev, id: "scki" ); |
748 | if (IS_ERR(ptr: pcm3168a->scki)) |
749 | return dev_err_probe(dev, err: PTR_ERR(ptr: pcm3168a->scki), |
750 | fmt: "failed to acquire clock 'scki'\n" ); |
751 | |
752 | ret = clk_prepare_enable(clk: pcm3168a->scki); |
753 | if (ret) { |
754 | dev_err(dev, "Failed to enable mclk: %d\n" , ret); |
755 | return ret; |
756 | } |
757 | |
758 | pcm3168a->sysclk = clk_get_rate(clk: pcm3168a->scki); |
759 | |
760 | for (i = 0; i < ARRAY_SIZE(pcm3168a->supplies); i++) |
761 | pcm3168a->supplies[i].supply = pcm3168a_supply_names[i]; |
762 | |
763 | ret = devm_regulator_bulk_get(dev, |
764 | ARRAY_SIZE(pcm3168a->supplies), consumers: pcm3168a->supplies); |
765 | if (ret) { |
766 | dev_err_probe(dev, err: ret, fmt: "failed to request supplies\n" ); |
767 | goto err_clk; |
768 | } |
769 | |
770 | ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies), |
771 | consumers: pcm3168a->supplies); |
772 | if (ret) { |
773 | dev_err(dev, "failed to enable supplies: %d\n" , ret); |
774 | goto err_clk; |
775 | } |
776 | |
777 | pcm3168a->regmap = regmap; |
778 | if (IS_ERR(ptr: pcm3168a->regmap)) { |
779 | ret = PTR_ERR(ptr: pcm3168a->regmap); |
780 | dev_err(dev, "failed to allocate regmap: %d\n" , ret); |
781 | goto err_regulator; |
782 | } |
783 | |
784 | if (pcm3168a->gpio_rst) { |
785 | /* |
786 | * The device is taken out from reset via GPIO line, wait for |
787 | * 3846 SCKI clock cycles for the internal reset de-assertion |
788 | */ |
789 | msleep(DIV_ROUND_UP(3846 * 1000, pcm3168a->sysclk)); |
790 | } else { |
791 | ret = pcm3168a_reset(pcm3168a); |
792 | if (ret) { |
793 | dev_err(dev, "Failed to reset device: %d\n" , ret); |
794 | goto err_regulator; |
795 | } |
796 | } |
797 | |
798 | pm_runtime_set_active(dev); |
799 | pm_runtime_enable(dev); |
800 | pm_runtime_idle(dev); |
801 | |
802 | memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv)); |
803 | ret = devm_snd_soc_register_component(dev, component_driver: &pcm3168a_driver, |
804 | dai_drv: pcm3168a->dai_drv, |
805 | ARRAY_SIZE(pcm3168a->dai_drv)); |
806 | if (ret) { |
807 | dev_err(dev, "failed to register component: %d\n" , ret); |
808 | goto err_regulator; |
809 | } |
810 | |
811 | return 0; |
812 | |
813 | err_regulator: |
814 | regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), |
815 | consumers: pcm3168a->supplies); |
816 | err_clk: |
817 | clk_disable_unprepare(clk: pcm3168a->scki); |
818 | |
819 | return ret; |
820 | } |
821 | EXPORT_SYMBOL_GPL(pcm3168a_probe); |
822 | |
823 | static void pcm3168a_disable(struct device *dev) |
824 | { |
825 | struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); |
826 | |
827 | regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), |
828 | consumers: pcm3168a->supplies); |
829 | clk_disable_unprepare(clk: pcm3168a->scki); |
830 | } |
831 | |
832 | void pcm3168a_remove(struct device *dev) |
833 | { |
834 | struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); |
835 | |
836 | /* |
837 | * The RST is low active, we want the GPIO line to be low when the |
838 | * driver is removed, so set level to 1 which in practice means |
839 | * ASSERTED: |
840 | * The asserted level of GPIO_ACTIVE_LOW is LOW. |
841 | */ |
842 | gpiod_set_value_cansleep(desc: pcm3168a->gpio_rst, value: 1); |
843 | pm_runtime_disable(dev); |
844 | #ifndef CONFIG_PM |
845 | pcm3168a_disable(dev); |
846 | #endif |
847 | } |
848 | EXPORT_SYMBOL_GPL(pcm3168a_remove); |
849 | |
850 | #ifdef CONFIG_PM |
851 | static int pcm3168a_rt_resume(struct device *dev) |
852 | { |
853 | struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); |
854 | int ret; |
855 | |
856 | ret = clk_prepare_enable(clk: pcm3168a->scki); |
857 | if (ret) { |
858 | dev_err(dev, "Failed to enable mclk: %d\n" , ret); |
859 | return ret; |
860 | } |
861 | |
862 | ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies), |
863 | consumers: pcm3168a->supplies); |
864 | if (ret) { |
865 | dev_err(dev, "Failed to enable supplies: %d\n" , ret); |
866 | goto err_clk; |
867 | } |
868 | |
869 | ret = pcm3168a_reset(pcm3168a); |
870 | if (ret) { |
871 | dev_err(dev, "Failed to reset device: %d\n" , ret); |
872 | goto err_regulator; |
873 | } |
874 | |
875 | regcache_cache_only(map: pcm3168a->regmap, enable: false); |
876 | |
877 | regcache_mark_dirty(map: pcm3168a->regmap); |
878 | |
879 | ret = regcache_sync(map: pcm3168a->regmap); |
880 | if (ret) { |
881 | dev_err(dev, "Failed to sync regmap: %d\n" , ret); |
882 | goto err_regulator; |
883 | } |
884 | |
885 | return 0; |
886 | |
887 | err_regulator: |
888 | regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), |
889 | consumers: pcm3168a->supplies); |
890 | err_clk: |
891 | clk_disable_unprepare(clk: pcm3168a->scki); |
892 | |
893 | return ret; |
894 | } |
895 | |
896 | static int pcm3168a_rt_suspend(struct device *dev) |
897 | { |
898 | struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); |
899 | |
900 | regcache_cache_only(map: pcm3168a->regmap, enable: true); |
901 | |
902 | pcm3168a_disable(dev); |
903 | |
904 | return 0; |
905 | } |
906 | #endif |
907 | |
908 | const struct dev_pm_ops pcm3168a_pm_ops = { |
909 | SET_RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL) |
910 | }; |
911 | EXPORT_SYMBOL_GPL(pcm3168a_pm_ops); |
912 | |
913 | MODULE_DESCRIPTION("PCM3168A codec driver" ); |
914 | MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>" ); |
915 | MODULE_LICENSE("GPL v2" ); |
916 | |