1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // rt712-sdca-dmic.c -- rt712 SDCA DMIC ALSA SoC audio driver |
4 | // |
5 | // Copyright(c) 2023 Realtek Semiconductor Corp. |
6 | // |
7 | // |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/mod_devicetable.h> |
11 | #include <linux/pm_runtime.h> |
12 | #include <linux/soundwire/sdw_registers.h> |
13 | #include <linux/slab.h> |
14 | #include <sound/core.h> |
15 | #include <sound/pcm.h> |
16 | #include <sound/pcm_params.h> |
17 | #include <sound/tlv.h> |
18 | #include "rt712-sdca.h" |
19 | #include "rt712-sdca-dmic.h" |
20 | |
21 | static bool rt712_sdca_dmic_readable_register(struct device *dev, unsigned int reg) |
22 | { |
23 | switch (reg) { |
24 | case 0x201a ... 0x201f: |
25 | case 0x2029 ... 0x202a: |
26 | case 0x202d ... 0x2034: |
27 | case 0x2230 ... 0x2232: |
28 | case 0x2f01 ... 0x2f0a: |
29 | case 0x2f35 ... 0x2f36: |
30 | case 0x2f52: |
31 | case 0x2f58 ... 0x2f59: |
32 | case 0x3201: |
33 | case 0x320c: |
34 | return true; |
35 | default: |
36 | return false; |
37 | } |
38 | } |
39 | |
40 | static bool rt712_sdca_dmic_volatile_register(struct device *dev, unsigned int reg) |
41 | { |
42 | switch (reg) { |
43 | case 0x201b: |
44 | case 0x201c: |
45 | case 0x201d: |
46 | case 0x201f: |
47 | case 0x202d ... 0x202f: |
48 | case 0x2230: |
49 | case 0x2f01: |
50 | case 0x2f35: |
51 | case 0x320c: |
52 | return true; |
53 | default: |
54 | return false; |
55 | } |
56 | } |
57 | |
58 | static bool rt712_sdca_dmic_mbq_readable_register(struct device *dev, unsigned int reg) |
59 | { |
60 | switch (reg) { |
61 | case 0x2000000 ... 0x200008e: |
62 | case 0x5300000 ... 0x530000e: |
63 | case 0x5400000 ... 0x540000e: |
64 | case 0x5600000 ... 0x5600008: |
65 | case 0x5700000 ... 0x570000d: |
66 | case 0x5800000 ... 0x5800021: |
67 | case 0x5900000 ... 0x5900028: |
68 | case 0x5a00000 ... 0x5a00009: |
69 | case 0x5b00000 ... 0x5b00051: |
70 | case 0x5c00000 ... 0x5c0009a: |
71 | case 0x5d00000 ... 0x5d00009: |
72 | case 0x5f00000 ... 0x5f00030: |
73 | case 0x6100000 ... 0x6100068: |
74 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01): |
75 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02): |
76 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03): |
77 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04): |
78 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01): |
79 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02): |
80 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03): |
81 | case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04): |
82 | return true; |
83 | default: |
84 | return false; |
85 | } |
86 | } |
87 | |
88 | static bool rt712_sdca_dmic_mbq_volatile_register(struct device *dev, unsigned int reg) |
89 | { |
90 | switch (reg) { |
91 | case 0x2000000: |
92 | case 0x200001a: |
93 | case 0x2000024: |
94 | case 0x2000046: |
95 | case 0x200008a: |
96 | case 0x5800000: |
97 | case 0x5800001: |
98 | case 0x6100008: |
99 | return true; |
100 | default: |
101 | return false; |
102 | } |
103 | } |
104 | |
105 | static const struct regmap_config rt712_sdca_dmic_regmap = { |
106 | .reg_bits = 32, |
107 | .val_bits = 8, |
108 | .readable_reg = rt712_sdca_dmic_readable_register, |
109 | .volatile_reg = rt712_sdca_dmic_volatile_register, |
110 | .max_register = 0x40981300, |
111 | .reg_defaults = rt712_sdca_dmic_reg_defaults, |
112 | .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_reg_defaults), |
113 | .cache_type = REGCACHE_MAPLE, |
114 | .use_single_read = true, |
115 | .use_single_write = true, |
116 | }; |
117 | |
118 | static const struct regmap_config rt712_sdca_dmic_mbq_regmap = { |
119 | .name = "sdw-mbq" , |
120 | .reg_bits = 32, |
121 | .val_bits = 16, |
122 | .readable_reg = rt712_sdca_dmic_mbq_readable_register, |
123 | .volatile_reg = rt712_sdca_dmic_mbq_volatile_register, |
124 | .max_register = 0x40800f14, |
125 | .reg_defaults = rt712_sdca_dmic_mbq_defaults, |
126 | .num_reg_defaults = ARRAY_SIZE(rt712_sdca_dmic_mbq_defaults), |
127 | .cache_type = REGCACHE_MAPLE, |
128 | .use_single_read = true, |
129 | .use_single_write = true, |
130 | }; |
131 | |
132 | static int rt712_sdca_dmic_index_write(struct rt712_sdca_dmic_priv *rt712, |
133 | unsigned int nid, unsigned int reg, unsigned int value) |
134 | { |
135 | int ret; |
136 | struct regmap *regmap = rt712->mbq_regmap; |
137 | unsigned int addr = (nid << 20) | reg; |
138 | |
139 | ret = regmap_write(map: regmap, reg: addr, val: value); |
140 | if (ret < 0) |
141 | dev_err(&rt712->slave->dev, |
142 | "%s: Failed to set private value: %06x <= %04x ret=%d\n" , |
143 | __func__, addr, value, ret); |
144 | |
145 | return ret; |
146 | } |
147 | |
148 | static int rt712_sdca_dmic_index_read(struct rt712_sdca_dmic_priv *rt712, |
149 | unsigned int nid, unsigned int reg, unsigned int *value) |
150 | { |
151 | int ret; |
152 | struct regmap *regmap = rt712->mbq_regmap; |
153 | unsigned int addr = (nid << 20) | reg; |
154 | |
155 | ret = regmap_read(map: regmap, reg: addr, val: value); |
156 | if (ret < 0) |
157 | dev_err(&rt712->slave->dev, |
158 | "%s: Failed to get private value: %06x => %04x ret=%d\n" , |
159 | __func__, addr, *value, ret); |
160 | |
161 | return ret; |
162 | } |
163 | |
164 | static int rt712_sdca_dmic_index_update_bits(struct rt712_sdca_dmic_priv *rt712, |
165 | unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) |
166 | { |
167 | unsigned int tmp; |
168 | int ret; |
169 | |
170 | ret = rt712_sdca_dmic_index_read(rt712, nid, reg, value: &tmp); |
171 | if (ret < 0) |
172 | return ret; |
173 | |
174 | set_mask_bits(&tmp, mask, val); |
175 | return rt712_sdca_dmic_index_write(rt712, nid, reg, value: tmp); |
176 | } |
177 | |
178 | static int rt712_sdca_dmic_io_init(struct device *dev, struct sdw_slave *slave) |
179 | { |
180 | struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); |
181 | |
182 | if (rt712->hw_init) |
183 | return 0; |
184 | |
185 | regcache_cache_only(map: rt712->regmap, enable: false); |
186 | regcache_cache_only(map: rt712->mbq_regmap, enable: false); |
187 | if (rt712->first_hw_init) { |
188 | regcache_cache_bypass(map: rt712->regmap, enable: true); |
189 | regcache_cache_bypass(map: rt712->mbq_regmap, enable: true); |
190 | } else { |
191 | /* |
192 | * PM runtime status is marked as 'active' only when a Slave reports as Attached |
193 | */ |
194 | |
195 | /* update count of parent 'active' children */ |
196 | pm_runtime_set_active(dev: &slave->dev); |
197 | } |
198 | |
199 | pm_runtime_get_noresume(dev: &slave->dev); |
200 | |
201 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
202 | RT712_ADC0A_08_PDE_FLOAT_CTL, value: 0x1112); |
203 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
204 | RT712_ADC0B_11_PDE_FLOAT_CTL, value: 0x1111); |
205 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
206 | RT712_DMIC1_2_PDE_FLOAT_CTL, value: 0x1111); |
207 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
208 | RT712_I2S_IN_OUT_PDE_FLOAT_CTL, value: 0x1155); |
209 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
210 | RT712_DMIC_ENT_FLOAT_CTL, value: 0x2626); |
211 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
212 | RT712_ADC_ENT_FLOAT_CTL, value: 0x1e19); |
213 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
214 | RT712_DMIC_GAIN_ENT_FLOAT_CTL0, value: 0x1515); |
215 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
216 | RT712_ADC_VOL_CH_FLOAT_CTL2, value: 0x0304); |
217 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
218 | RT712_DMIC_GAIN_ENT_FLOAT_CTL2, value: 0x0304); |
219 | rt712_sdca_dmic_index_write(rt712, RT712_VENDOR_HDA_CTL, |
220 | RT712_HDA_LEGACY_CONFIG_CTL0, value: 0x0050); |
221 | regmap_write(map: rt712->regmap, |
222 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT26, RT712_SDCA_CTL_VENDOR_DEF, 0), val: 0x01); |
223 | rt712_sdca_dmic_index_write(rt712, RT712_ULTRA_SOUND_DET, |
224 | RT712_ULTRA_SOUND_DETECTOR6, value: 0x3200); |
225 | regmap_write(map: rt712->regmap, RT712_RC_CAL, val: 0x23); |
226 | regmap_write(map: rt712->regmap, reg: 0x2f52, val: 0x00); |
227 | |
228 | if (rt712->first_hw_init) { |
229 | regcache_cache_bypass(map: rt712->regmap, enable: false); |
230 | regcache_mark_dirty(map: rt712->regmap); |
231 | regcache_cache_bypass(map: rt712->mbq_regmap, enable: false); |
232 | regcache_mark_dirty(map: rt712->mbq_regmap); |
233 | } else |
234 | rt712->first_hw_init = true; |
235 | |
236 | /* Mark Slave initialization complete */ |
237 | rt712->hw_init = true; |
238 | |
239 | pm_runtime_mark_last_busy(dev: &slave->dev); |
240 | pm_runtime_put_autosuspend(dev: &slave->dev); |
241 | |
242 | dev_dbg(&slave->dev, "%s hw_init complete\n" , __func__); |
243 | return 0; |
244 | } |
245 | |
246 | static int rt712_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, |
247 | struct snd_ctl_elem_value *ucontrol) |
248 | { |
249 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
250 | struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
251 | struct rt712_sdca_dmic_kctrl_priv *p = |
252 | (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; |
253 | unsigned int regvalue, ctl, i; |
254 | unsigned int adc_vol_flag = 0; |
255 | const unsigned int interval_offset = 0xc0; |
256 | |
257 | if (strstr(ucontrol->id.name, "FU1E Capture Volume" )) |
258 | adc_vol_flag = 1; |
259 | |
260 | /* check all channels */ |
261 | for (i = 0; i < p->count; i++) { |
262 | regmap_read(map: rt712->mbq_regmap, reg: p->reg_base + i, val: ®value); |
263 | |
264 | if (!adc_vol_flag) /* boost gain */ |
265 | ctl = regvalue / 0x0a00; |
266 | else { /* ADC gain */ |
267 | if (adc_vol_flag) |
268 | ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); |
269 | else |
270 | ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); |
271 | } |
272 | |
273 | ucontrol->value.integer.value[i] = ctl; |
274 | } |
275 | |
276 | return 0; |
277 | } |
278 | |
279 | static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, |
280 | struct snd_ctl_elem_value *ucontrol) |
281 | { |
282 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
283 | struct rt712_sdca_dmic_kctrl_priv *p = |
284 | (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; |
285 | struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
286 | unsigned int gain_val[4]; |
287 | unsigned int i, adc_vol_flag = 0, changed = 0; |
288 | unsigned int regvalue[4]; |
289 | const unsigned int interval_offset = 0xc0; |
290 | int err; |
291 | |
292 | if (strstr(ucontrol->id.name, "FU1E Capture Volume" )) |
293 | adc_vol_flag = 1; |
294 | |
295 | /* check all channels */ |
296 | for (i = 0; i < p->count; i++) { |
297 | regmap_read(map: rt712->mbq_regmap, reg: p->reg_base + i, val: ®value[i]); |
298 | |
299 | gain_val[i] = ucontrol->value.integer.value[i]; |
300 | if (gain_val[i] > p->max) |
301 | gain_val[i] = p->max; |
302 | |
303 | if (!adc_vol_flag) /* boost gain */ |
304 | gain_val[i] = gain_val[i] * 0x0a00; |
305 | else { /* ADC gain */ |
306 | gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset); |
307 | gain_val[i] &= 0xffff; |
308 | } |
309 | |
310 | if (regvalue[i] != gain_val[i]) |
311 | changed = 1; |
312 | } |
313 | |
314 | if (!changed) |
315 | return 0; |
316 | |
317 | for (i = 0; i < p->count; i++) { |
318 | err = regmap_write(map: rt712->mbq_regmap, reg: p->reg_base + i, val: gain_val[i]); |
319 | if (err < 0) |
320 | dev_err(&rt712->slave->dev, "%s: 0x%08x can't be set\n" , |
321 | __func__, p->reg_base + i); |
322 | } |
323 | |
324 | return changed; |
325 | } |
326 | |
327 | static int rt712_sdca_set_fu1e_capture_ctl(struct rt712_sdca_dmic_priv *rt712) |
328 | { |
329 | int err, i; |
330 | unsigned int ch_mute; |
331 | |
332 | for (i = 0; i < ARRAY_SIZE(rt712->fu1e_mixer_mute); i++) { |
333 | ch_mute = (rt712->fu1e_dapm_mute || rt712->fu1e_mixer_mute[i]) ? 0x01 : 0x00; |
334 | err = regmap_write(map: rt712->regmap, |
335 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, |
336 | RT712_SDCA_CTL_FU_MUTE, CH_01) + i, val: ch_mute); |
337 | if (err < 0) |
338 | return err; |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static int rt712_sdca_dmic_fu1e_capture_get(struct snd_kcontrol *kcontrol, |
345 | struct snd_ctl_elem_value *ucontrol) |
346 | { |
347 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
348 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
349 | struct rt712_sdca_dmic_kctrl_priv *p = |
350 | (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; |
351 | unsigned int i; |
352 | |
353 | for (i = 0; i < p->count; i++) |
354 | ucontrol->value.integer.value[i] = !rt712->fu1e_mixer_mute[i]; |
355 | |
356 | return 0; |
357 | } |
358 | |
359 | static int rt712_sdca_dmic_fu1e_capture_put(struct snd_kcontrol *kcontrol, |
360 | struct snd_ctl_elem_value *ucontrol) |
361 | { |
362 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
363 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
364 | struct rt712_sdca_dmic_kctrl_priv *p = |
365 | (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; |
366 | int err, changed = 0, i; |
367 | |
368 | for (i = 0; i < p->count; i++) { |
369 | if (rt712->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i]) |
370 | changed = 1; |
371 | rt712->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i]; |
372 | } |
373 | |
374 | err = rt712_sdca_set_fu1e_capture_ctl(rt712); |
375 | if (err < 0) |
376 | return err; |
377 | |
378 | return changed; |
379 | } |
380 | |
381 | static int rt712_sdca_fu_info(struct snd_kcontrol *kcontrol, |
382 | struct snd_ctl_elem_info *uinfo) |
383 | { |
384 | struct rt712_sdca_dmic_kctrl_priv *p = |
385 | (struct rt712_sdca_dmic_kctrl_priv *)kcontrol->private_value; |
386 | |
387 | if (p->max == 1) |
388 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
389 | else |
390 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
391 | uinfo->count = p->count; |
392 | uinfo->value.integer.min = 0; |
393 | uinfo->value.integer.max = p->max; |
394 | return 0; |
395 | } |
396 | |
397 | #define RT712_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ |
398 | ((unsigned long)&(struct rt712_sdca_dmic_kctrl_priv) \ |
399 | {.reg_base = xreg_base, .count = xcount, .max = xmax, \ |
400 | .invert = xinvert}) |
401 | |
402 | #define RT712_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount) \ |
403 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
404 | .info = rt712_sdca_fu_info, \ |
405 | .get = rt712_sdca_dmic_fu1e_capture_get, \ |
406 | .put = rt712_sdca_dmic_fu1e_capture_put, \ |
407 | .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} |
408 | |
409 | #define RT712_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ |
410 | xhandler_put, xcount, xmax, tlv_array) \ |
411 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
412 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ |
413 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ |
414 | .tlv.p = (tlv_array), \ |
415 | .info = rt712_sdca_fu_info, \ |
416 | .get = xhandler_get, .put = xhandler_put, \ |
417 | .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } |
418 | |
419 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); |
420 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); |
421 | |
422 | static const struct snd_kcontrol_new rt712_sdca_dmic_snd_controls[] = { |
423 | RT712_SDCA_FU_CTRL("FU1E Capture Switch" , |
424 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), |
425 | 1, 1, 4), |
426 | RT712_SDCA_EXT_TLV("FU1E Capture Volume" , |
427 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), |
428 | rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 0x3f, in_vol_tlv), |
429 | RT712_SDCA_EXT_TLV("FU15 Boost Volume" , |
430 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), |
431 | rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 3, mic_vol_tlv), |
432 | }; |
433 | |
434 | static int rt712_sdca_dmic_mux_get(struct snd_kcontrol *kcontrol, |
435 | struct snd_ctl_elem_value *ucontrol) |
436 | { |
437 | struct snd_soc_component *component = |
438 | snd_soc_dapm_kcontrol_component(kcontrol); |
439 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
440 | unsigned int val = 0, mask_sft; |
441 | |
442 | if (strstr(ucontrol->id.name, "ADC 25 Mux" )) |
443 | mask_sft = 8; |
444 | else if (strstr(ucontrol->id.name, "ADC 26 Mux" )) |
445 | mask_sft = 4; |
446 | else |
447 | return -EINVAL; |
448 | |
449 | rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, |
450 | RT712_HDA_LEGACY_MUX_CTL0, value: &val); |
451 | |
452 | ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; |
453 | |
454 | return 0; |
455 | } |
456 | |
457 | static int rt712_sdca_dmic_mux_put(struct snd_kcontrol *kcontrol, |
458 | struct snd_ctl_elem_value *ucontrol) |
459 | { |
460 | struct snd_soc_component *component = |
461 | snd_soc_dapm_kcontrol_component(kcontrol); |
462 | struct snd_soc_dapm_context *dapm = |
463 | snd_soc_dapm_kcontrol_dapm(kcontrol); |
464 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
465 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
466 | unsigned int *item = ucontrol->value.enumerated.item; |
467 | unsigned int val, val2 = 0, change, mask_sft; |
468 | |
469 | if (item[0] >= e->items) |
470 | return -EINVAL; |
471 | |
472 | if (strstr(ucontrol->id.name, "ADC 25 Mux" )) |
473 | mask_sft = 8; |
474 | else if (strstr(ucontrol->id.name, "ADC 26 Mux" )) |
475 | mask_sft = 4; |
476 | else |
477 | return -EINVAL; |
478 | |
479 | val = snd_soc_enum_item_to_val(e, item: item[0]) << e->shift_l; |
480 | |
481 | rt712_sdca_dmic_index_read(rt712, RT712_VENDOR_HDA_CTL, |
482 | RT712_HDA_LEGACY_MUX_CTL0, value: &val2); |
483 | val2 = (0x7 << mask_sft) & val2; |
484 | |
485 | if (val == val2) |
486 | change = 0; |
487 | else |
488 | change = 1; |
489 | |
490 | if (change) |
491 | rt712_sdca_dmic_index_update_bits(rt712, RT712_VENDOR_HDA_CTL, |
492 | RT712_HDA_LEGACY_MUX_CTL0, mask: 0x7 << mask_sft, |
493 | val: val << mask_sft); |
494 | |
495 | snd_soc_dapm_mux_update_power(dapm, kcontrol, |
496 | mux: item[0], e, NULL); |
497 | |
498 | return change; |
499 | } |
500 | |
501 | static const char * const adc_mux_text[] = { |
502 | "DMIC1" , |
503 | "DMIC2" , |
504 | }; |
505 | |
506 | static SOC_ENUM_SINGLE_DECL( |
507 | rt712_adc25_enum, SND_SOC_NOPM, 0, adc_mux_text); |
508 | |
509 | static SOC_ENUM_SINGLE_DECL( |
510 | rt712_adc26_enum, SND_SOC_NOPM, 0, adc_mux_text); |
511 | |
512 | static const struct snd_kcontrol_new rt712_sdca_dmic_adc25_mux = |
513 | SOC_DAPM_ENUM_EXT("ADC 25 Mux" , rt712_adc25_enum, |
514 | rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); |
515 | |
516 | static const struct snd_kcontrol_new rt712_sdca_dmic_adc26_mux = |
517 | SOC_DAPM_ENUM_EXT("ADC 26 Mux" , rt712_adc26_enum, |
518 | rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); |
519 | |
520 | static int rt712_sdca_dmic_fu1e_event(struct snd_soc_dapm_widget *w, |
521 | struct snd_kcontrol *kcontrol, int event) |
522 | { |
523 | struct snd_soc_component *component = |
524 | snd_soc_dapm_to_component(dapm: w->dapm); |
525 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
526 | |
527 | switch (event) { |
528 | case SND_SOC_DAPM_POST_PMU: |
529 | rt712->fu1e_dapm_mute = false; |
530 | rt712_sdca_set_fu1e_capture_ctl(rt712); |
531 | break; |
532 | case SND_SOC_DAPM_PRE_PMD: |
533 | rt712->fu1e_dapm_mute = true; |
534 | rt712_sdca_set_fu1e_capture_ctl(rt712); |
535 | break; |
536 | } |
537 | return 0; |
538 | } |
539 | |
540 | static int rt712_sdca_dmic_pde11_event(struct snd_soc_dapm_widget *w, |
541 | struct snd_kcontrol *kcontrol, int event) |
542 | { |
543 | struct snd_soc_component *component = |
544 | snd_soc_dapm_to_component(dapm: w->dapm); |
545 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
546 | unsigned char ps0 = 0x0, ps3 = 0x3; |
547 | |
548 | switch (event) { |
549 | case SND_SOC_DAPM_POST_PMU: |
550 | regmap_write(map: rt712->regmap, |
551 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, |
552 | RT712_SDCA_CTL_REQ_POWER_STATE, 0), |
553 | val: ps0); |
554 | break; |
555 | case SND_SOC_DAPM_PRE_PMD: |
556 | regmap_write(map: rt712->regmap, |
557 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, |
558 | RT712_SDCA_CTL_REQ_POWER_STATE, 0), |
559 | val: ps3); |
560 | break; |
561 | } |
562 | return 0; |
563 | } |
564 | |
565 | static const struct snd_soc_dapm_widget rt712_sdca_dmic_dapm_widgets[] = { |
566 | SND_SOC_DAPM_INPUT("DMIC1" ), |
567 | SND_SOC_DAPM_INPUT("DMIC2" ), |
568 | |
569 | SND_SOC_DAPM_SUPPLY("PDE 11" , SND_SOC_NOPM, 0, 0, |
570 | rt712_sdca_dmic_pde11_event, |
571 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
572 | |
573 | SND_SOC_DAPM_ADC_E("FU 1E" , NULL, SND_SOC_NOPM, 0, 0, |
574 | rt712_sdca_dmic_fu1e_event, |
575 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
576 | SND_SOC_DAPM_MUX("ADC 25 Mux" , SND_SOC_NOPM, 0, 0, |
577 | &rt712_sdca_dmic_adc25_mux), |
578 | SND_SOC_DAPM_MUX("ADC 26 Mux" , SND_SOC_NOPM, 0, 0, |
579 | &rt712_sdca_dmic_adc26_mux), |
580 | |
581 | SND_SOC_DAPM_AIF_OUT("DP2TX" , "DP2 Capture" , 0, SND_SOC_NOPM, 0, 0), |
582 | }; |
583 | |
584 | static const struct snd_soc_dapm_route rt712_sdca_dmic_audio_map[] = { |
585 | {"DP2TX" , NULL, "FU 1E" }, |
586 | |
587 | {"FU 1E" , NULL, "PDE 11" }, |
588 | {"FU 1E" , NULL, "ADC 25 Mux" }, |
589 | {"FU 1E" , NULL, "ADC 26 Mux" }, |
590 | {"ADC 25 Mux" , "DMIC1" , "DMIC1" }, |
591 | {"ADC 25 Mux" , "DMIC2" , "DMIC2" }, |
592 | {"ADC 26 Mux" , "DMIC1" , "DMIC1" }, |
593 | {"ADC 26 Mux" , "DMIC2" , "DMIC2" }, |
594 | }; |
595 | |
596 | static int rt712_sdca_dmic_probe(struct snd_soc_component *component) |
597 | { |
598 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
599 | int ret; |
600 | |
601 | rt712->component = component; |
602 | |
603 | if (!rt712->first_hw_init) |
604 | return 0; |
605 | |
606 | ret = pm_runtime_resume(dev: component->dev); |
607 | if (ret < 0 && ret != -EACCES) |
608 | return ret; |
609 | |
610 | return 0; |
611 | } |
612 | |
613 | static const struct snd_soc_component_driver soc_sdca_dev_rt712_dmic = { |
614 | .probe = rt712_sdca_dmic_probe, |
615 | .controls = rt712_sdca_dmic_snd_controls, |
616 | .num_controls = ARRAY_SIZE(rt712_sdca_dmic_snd_controls), |
617 | .dapm_widgets = rt712_sdca_dmic_dapm_widgets, |
618 | .num_dapm_widgets = ARRAY_SIZE(rt712_sdca_dmic_dapm_widgets), |
619 | .dapm_routes = rt712_sdca_dmic_audio_map, |
620 | .num_dapm_routes = ARRAY_SIZE(rt712_sdca_dmic_audio_map), |
621 | .endianness = 1, |
622 | }; |
623 | |
624 | static int rt712_sdca_dmic_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, |
625 | int direction) |
626 | { |
627 | snd_soc_dai_dma_data_set(dai, stream: direction, data: sdw_stream); |
628 | |
629 | return 0; |
630 | } |
631 | |
632 | static void rt712_sdca_dmic_shutdown(struct snd_pcm_substream *substream, |
633 | struct snd_soc_dai *dai) |
634 | { |
635 | snd_soc_dai_set_dma_data(dai, substream, NULL); |
636 | } |
637 | |
638 | static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream, |
639 | struct snd_pcm_hw_params *params, |
640 | struct snd_soc_dai *dai) |
641 | { |
642 | struct snd_soc_component *component = dai->component; |
643 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
644 | struct sdw_stream_config stream_config; |
645 | struct sdw_port_config port_config; |
646 | struct sdw_stream_runtime *sdw_stream; |
647 | int retval, num_channels; |
648 | unsigned int sampling_rate; |
649 | |
650 | dev_dbg(dai->dev, "%s %s" , __func__, dai->name); |
651 | sdw_stream = snd_soc_dai_get_dma_data(dai, substream); |
652 | |
653 | if (!sdw_stream) |
654 | return -EINVAL; |
655 | |
656 | if (!rt712->slave) |
657 | return -EINVAL; |
658 | |
659 | stream_config.frame_rate = params_rate(p: params); |
660 | stream_config.ch_count = params_channels(p: params); |
661 | stream_config.bps = snd_pcm_format_width(format: params_format(p: params)); |
662 | stream_config.direction = SDW_DATA_DIR_TX; |
663 | |
664 | num_channels = params_channels(p: params); |
665 | port_config.ch_mask = GENMASK(num_channels - 1, 0); |
666 | port_config.num = 2; |
667 | |
668 | retval = sdw_stream_add_slave(slave: rt712->slave, stream_config: &stream_config, |
669 | port_config: &port_config, num_ports: 1, stream: sdw_stream); |
670 | if (retval) { |
671 | dev_err(dai->dev, "%s: Unable to configure port\n" , __func__); |
672 | return retval; |
673 | } |
674 | |
675 | if (params_channels(p: params) > 4) { |
676 | dev_err(component->dev, "%s: Unsupported channels %d\n" , |
677 | __func__, params_channels(params)); |
678 | return -EINVAL; |
679 | } |
680 | |
681 | /* sampling rate configuration */ |
682 | switch (params_rate(p: params)) { |
683 | case 16000: |
684 | sampling_rate = RT712_SDCA_RATE_16000HZ; |
685 | break; |
686 | case 32000: |
687 | sampling_rate = RT712_SDCA_RATE_32000HZ; |
688 | break; |
689 | case 44100: |
690 | sampling_rate = RT712_SDCA_RATE_44100HZ; |
691 | break; |
692 | case 48000: |
693 | sampling_rate = RT712_SDCA_RATE_48000HZ; |
694 | break; |
695 | case 96000: |
696 | sampling_rate = RT712_SDCA_RATE_96000HZ; |
697 | break; |
698 | case 192000: |
699 | sampling_rate = RT712_SDCA_RATE_192000HZ; |
700 | break; |
701 | default: |
702 | dev_err(component->dev, "%s: Rate %d is not supported\n" , |
703 | __func__, params_rate(params)); |
704 | return -EINVAL; |
705 | } |
706 | |
707 | /* set sampling frequency */ |
708 | regmap_write(map: rt712->regmap, |
709 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
710 | val: sampling_rate); |
711 | regmap_write(map: rt712->regmap, |
712 | SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
713 | val: sampling_rate); |
714 | |
715 | return 0; |
716 | } |
717 | |
718 | static int rt712_sdca_dmic_hw_free(struct snd_pcm_substream *substream, |
719 | struct snd_soc_dai *dai) |
720 | { |
721 | struct snd_soc_component *component = dai->component; |
722 | struct rt712_sdca_dmic_priv *rt712 = snd_soc_component_get_drvdata(c: component); |
723 | struct sdw_stream_runtime *sdw_stream = |
724 | snd_soc_dai_get_dma_data(dai, substream); |
725 | |
726 | if (!rt712->slave) |
727 | return -EINVAL; |
728 | |
729 | sdw_stream_remove_slave(slave: rt712->slave, stream: sdw_stream); |
730 | return 0; |
731 | } |
732 | |
733 | #define RT712_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
734 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) |
735 | #define RT712_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
736 | SNDRV_PCM_FMTBIT_S24_LE) |
737 | |
738 | static const struct snd_soc_dai_ops rt712_sdca_dmic_ops = { |
739 | .hw_params = rt712_sdca_dmic_hw_params, |
740 | .hw_free = rt712_sdca_dmic_hw_free, |
741 | .set_stream = rt712_sdca_dmic_set_sdw_stream, |
742 | .shutdown = rt712_sdca_dmic_shutdown, |
743 | }; |
744 | |
745 | static struct snd_soc_dai_driver rt712_sdca_dmic_dai[] = { |
746 | { |
747 | .name = "rt712-sdca-dmic-aif1" , |
748 | .id = RT712_AIF1, |
749 | .capture = { |
750 | .stream_name = "DP2 Capture" , |
751 | .channels_min = 1, |
752 | .channels_max = 4, |
753 | .rates = RT712_STEREO_RATES, |
754 | .formats = RT712_FORMATS, |
755 | }, |
756 | .ops = &rt712_sdca_dmic_ops, |
757 | }, |
758 | }; |
759 | |
760 | static int rt712_sdca_dmic_init(struct device *dev, struct regmap *regmap, |
761 | struct regmap *mbq_regmap, struct sdw_slave *slave) |
762 | { |
763 | struct rt712_sdca_dmic_priv *rt712; |
764 | int ret; |
765 | |
766 | rt712 = devm_kzalloc(dev, size: sizeof(*rt712), GFP_KERNEL); |
767 | if (!rt712) |
768 | return -ENOMEM; |
769 | |
770 | dev_set_drvdata(dev, data: rt712); |
771 | rt712->slave = slave; |
772 | rt712->regmap = regmap; |
773 | rt712->mbq_regmap = mbq_regmap; |
774 | |
775 | regcache_cache_only(map: rt712->regmap, enable: true); |
776 | regcache_cache_only(map: rt712->mbq_regmap, enable: true); |
777 | |
778 | /* |
779 | * Mark hw_init to false |
780 | * HW init will be performed when device reports present |
781 | */ |
782 | rt712->hw_init = false; |
783 | rt712->first_hw_init = false; |
784 | rt712->fu1e_dapm_mute = true; |
785 | rt712->fu1e_mixer_mute[0] = rt712->fu1e_mixer_mute[1] = |
786 | rt712->fu1e_mixer_mute[2] = rt712->fu1e_mixer_mute[3] = true; |
787 | |
788 | ret = devm_snd_soc_register_component(dev, |
789 | component_driver: &soc_sdca_dev_rt712_dmic, |
790 | dai_drv: rt712_sdca_dmic_dai, |
791 | ARRAY_SIZE(rt712_sdca_dmic_dai)); |
792 | if (ret < 0) |
793 | return ret; |
794 | |
795 | /* set autosuspend parameters */ |
796 | pm_runtime_set_autosuspend_delay(dev, delay: 3000); |
797 | pm_runtime_use_autosuspend(dev); |
798 | |
799 | /* make sure the device does not suspend immediately */ |
800 | pm_runtime_mark_last_busy(dev); |
801 | |
802 | pm_runtime_enable(dev); |
803 | |
804 | /* important note: the device is NOT tagged as 'active' and will remain |
805 | * 'suspended' until the hardware is enumerated/initialized. This is required |
806 | * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently |
807 | * fail with -EACCESS because of race conditions between card creation and enumeration |
808 | */ |
809 | |
810 | dev_dbg(dev, "%s\n" , __func__); |
811 | |
812 | return 0; |
813 | } |
814 | |
815 | |
816 | static int rt712_sdca_dmic_update_status(struct sdw_slave *slave, |
817 | enum sdw_slave_status status) |
818 | { |
819 | struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev: &slave->dev); |
820 | |
821 | if (status == SDW_SLAVE_UNATTACHED) |
822 | rt712->hw_init = false; |
823 | |
824 | /* |
825 | * Perform initialization only if slave status is present and |
826 | * hw_init flag is false |
827 | */ |
828 | if (rt712->hw_init || status != SDW_SLAVE_ATTACHED) |
829 | return 0; |
830 | |
831 | /* perform I/O transfers required for Slave initialization */ |
832 | return rt712_sdca_dmic_io_init(dev: &slave->dev, slave); |
833 | } |
834 | |
835 | static int rt712_sdca_dmic_read_prop(struct sdw_slave *slave) |
836 | { |
837 | struct sdw_slave_prop *prop = &slave->prop; |
838 | int nval, i; |
839 | u32 bit; |
840 | unsigned long addr; |
841 | struct sdw_dpn_prop *dpn; |
842 | |
843 | prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; |
844 | prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; |
845 | |
846 | prop->paging_support = true; |
847 | |
848 | /* first we need to allocate memory for set bits in port lists */ |
849 | prop->source_ports = BIT(2); /* BITMAP: 00000100 */ |
850 | prop->sink_ports = 0; |
851 | |
852 | nval = hweight32(prop->source_ports); |
853 | prop->src_dpn_prop = devm_kcalloc(dev: &slave->dev, n: nval, |
854 | size: sizeof(*prop->src_dpn_prop), GFP_KERNEL); |
855 | if (!prop->src_dpn_prop) |
856 | return -ENOMEM; |
857 | |
858 | i = 0; |
859 | dpn = prop->src_dpn_prop; |
860 | addr = prop->source_ports; |
861 | for_each_set_bit(bit, &addr, 32) { |
862 | dpn[i].num = bit; |
863 | dpn[i].type = SDW_DPN_FULL; |
864 | dpn[i].simple_ch_prep_sm = true; |
865 | dpn[i].ch_prep_timeout = 10; |
866 | i++; |
867 | } |
868 | |
869 | /* set the timeout values */ |
870 | prop->clk_stop_timeout = 200; |
871 | |
872 | /* wake-up event */ |
873 | prop->wake_capable = 1; |
874 | |
875 | return 0; |
876 | } |
877 | |
878 | static const struct sdw_device_id rt712_sdca_dmic_id[] = { |
879 | SDW_SLAVE_ENTRY_EXT(0x025d, 0x1712, 0x3, 0x1, 0), |
880 | SDW_SLAVE_ENTRY_EXT(0x025d, 0x1713, 0x3, 0x1, 0), |
881 | SDW_SLAVE_ENTRY_EXT(0x025d, 0x1716, 0x3, 0x1, 0), |
882 | SDW_SLAVE_ENTRY_EXT(0x025d, 0x1717, 0x3, 0x1, 0), |
883 | {}, |
884 | }; |
885 | MODULE_DEVICE_TABLE(sdw, rt712_sdca_dmic_id); |
886 | |
887 | static int __maybe_unused rt712_sdca_dmic_dev_suspend(struct device *dev) |
888 | { |
889 | struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); |
890 | |
891 | if (!rt712->hw_init) |
892 | return 0; |
893 | |
894 | regcache_cache_only(map: rt712->regmap, enable: true); |
895 | regcache_cache_only(map: rt712->mbq_regmap, enable: true); |
896 | |
897 | return 0; |
898 | } |
899 | |
900 | static int __maybe_unused rt712_sdca_dmic_dev_system_suspend(struct device *dev) |
901 | { |
902 | struct rt712_sdca_dmic_priv *rt712_sdca = dev_get_drvdata(dev); |
903 | |
904 | if (!rt712_sdca->hw_init) |
905 | return 0; |
906 | |
907 | return rt712_sdca_dmic_dev_suspend(dev); |
908 | } |
909 | |
910 | #define RT712_PROBE_TIMEOUT 5000 |
911 | |
912 | static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev) |
913 | { |
914 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
915 | struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); |
916 | unsigned long time; |
917 | |
918 | if (!rt712->first_hw_init) |
919 | return 0; |
920 | |
921 | if (!slave->unattach_request) |
922 | goto regmap_sync; |
923 | |
924 | time = wait_for_completion_timeout(x: &slave->initialization_complete, |
925 | timeout: msecs_to_jiffies(RT712_PROBE_TIMEOUT)); |
926 | if (!time) { |
927 | dev_err(&slave->dev, "%s: Initialization not complete, timed out\n" , |
928 | __func__); |
929 | sdw_show_ping_status(bus: slave->bus, sync_delay: true); |
930 | |
931 | return -ETIMEDOUT; |
932 | } |
933 | |
934 | regmap_sync: |
935 | slave->unattach_request = 0; |
936 | regcache_cache_only(map: rt712->regmap, enable: false); |
937 | regcache_sync(map: rt712->regmap); |
938 | regcache_cache_only(map: rt712->mbq_regmap, enable: false); |
939 | regcache_sync(map: rt712->mbq_regmap); |
940 | return 0; |
941 | } |
942 | |
943 | static const struct dev_pm_ops rt712_sdca_dmic_pm = { |
944 | SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dmic_dev_system_suspend, rt712_sdca_dmic_dev_resume) |
945 | SET_RUNTIME_PM_OPS(rt712_sdca_dmic_dev_suspend, rt712_sdca_dmic_dev_resume, NULL) |
946 | }; |
947 | |
948 | |
949 | static const struct sdw_slave_ops rt712_sdca_dmic_slave_ops = { |
950 | .read_prop = rt712_sdca_dmic_read_prop, |
951 | .update_status = rt712_sdca_dmic_update_status, |
952 | }; |
953 | |
954 | static int rt712_sdca_dmic_sdw_probe(struct sdw_slave *slave, |
955 | const struct sdw_device_id *id) |
956 | { |
957 | struct regmap *regmap, *mbq_regmap; |
958 | |
959 | /* Regmap Initialization */ |
960 | mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt712_sdca_dmic_mbq_regmap); |
961 | if (IS_ERR(ptr: mbq_regmap)) |
962 | return PTR_ERR(ptr: mbq_regmap); |
963 | |
964 | regmap = devm_regmap_init_sdw(slave, &rt712_sdca_dmic_regmap); |
965 | if (IS_ERR(ptr: regmap)) |
966 | return PTR_ERR(ptr: regmap); |
967 | |
968 | return rt712_sdca_dmic_init(dev: &slave->dev, regmap, mbq_regmap, slave); |
969 | } |
970 | |
971 | static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave) |
972 | { |
973 | pm_runtime_disable(dev: &slave->dev); |
974 | |
975 | return 0; |
976 | } |
977 | |
978 | static struct sdw_driver rt712_sdca_dmic_sdw_driver = { |
979 | .driver = { |
980 | .name = "rt712-sdca-dmic" , |
981 | .owner = THIS_MODULE, |
982 | .pm = &rt712_sdca_dmic_pm, |
983 | }, |
984 | .probe = rt712_sdca_dmic_sdw_probe, |
985 | .remove = rt712_sdca_dmic_sdw_remove, |
986 | .ops = &rt712_sdca_dmic_slave_ops, |
987 | .id_table = rt712_sdca_dmic_id, |
988 | }; |
989 | module_sdw_driver(rt712_sdca_dmic_sdw_driver); |
990 | |
991 | MODULE_DESCRIPTION("ASoC RT712 SDCA DMIC SDW driver" ); |
992 | MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>" ); |
993 | MODULE_LICENSE("GPL" ); |
994 | |