1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Routines for control of the AK4117 via 4-wire serial interface |
4 | * IEC958 (S/PDIF) receiver by Asahi Kasei |
5 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
6 | */ |
7 | |
8 | #include <linux/slab.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/module.h> |
11 | #include <sound/core.h> |
12 | #include <sound/control.h> |
13 | #include <sound/pcm.h> |
14 | #include <sound/ak4117.h> |
15 | #include <sound/asoundef.h> |
16 | |
17 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>" ); |
18 | MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei" ); |
19 | MODULE_LICENSE("GPL" ); |
20 | |
21 | #define AK4117_ADDR 0x00 /* fixed address */ |
22 | |
23 | static void snd_ak4117_timer(struct timer_list *t); |
24 | |
25 | static void reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char val) |
26 | { |
27 | ak4117->write(ak4117->private_data, reg, val); |
28 | if (reg < sizeof(ak4117->regmap)) |
29 | ak4117->regmap[reg] = val; |
30 | } |
31 | |
32 | static inline unsigned char reg_read(struct ak4117 *ak4117, unsigned char reg) |
33 | { |
34 | return ak4117->read(ak4117->private_data, reg); |
35 | } |
36 | |
37 | #if 0 |
38 | static void reg_dump(struct ak4117 *ak4117) |
39 | { |
40 | int i; |
41 | |
42 | printk(KERN_DEBUG "AK4117 REG DUMP:\n" ); |
43 | for (i = 0; i < 0x1b; i++) |
44 | printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n" , i, reg_read(ak4117, i), i < sizeof(ak4117->regmap) ? ak4117->regmap[i] : 0); |
45 | } |
46 | #endif |
47 | |
48 | static void snd_ak4117_free(struct ak4117 *chip) |
49 | { |
50 | timer_shutdown_sync(timer: &chip->timer); |
51 | kfree(objp: chip); |
52 | } |
53 | |
54 | static int snd_ak4117_dev_free(struct snd_device *device) |
55 | { |
56 | struct ak4117 *chip = device->device_data; |
57 | snd_ak4117_free(chip); |
58 | return 0; |
59 | } |
60 | |
61 | int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, |
62 | const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117) |
63 | { |
64 | struct ak4117 *chip; |
65 | int err = 0; |
66 | unsigned char reg; |
67 | static const struct snd_device_ops ops = { |
68 | .dev_free = snd_ak4117_dev_free, |
69 | }; |
70 | |
71 | chip = kzalloc(size: sizeof(*chip), GFP_KERNEL); |
72 | if (chip == NULL) |
73 | return -ENOMEM; |
74 | spin_lock_init(&chip->lock); |
75 | chip->card = card; |
76 | chip->read = read; |
77 | chip->write = write; |
78 | chip->private_data = private_data; |
79 | timer_setup(&chip->timer, snd_ak4117_timer, 0); |
80 | |
81 | for (reg = 0; reg < 5; reg++) |
82 | chip->regmap[reg] = pgm[reg]; |
83 | snd_ak4117_reinit(ak4117: chip); |
84 | |
85 | chip->rcs0 = reg_read(ak4117: chip, AK4117_REG_RCS0) & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); |
86 | chip->rcs1 = reg_read(ak4117: chip, AK4117_REG_RCS1); |
87 | chip->rcs2 = reg_read(ak4117: chip, AK4117_REG_RCS2); |
88 | |
89 | err = snd_device_new(card, type: SNDRV_DEV_CODEC, device_data: chip, ops: &ops); |
90 | if (err < 0) |
91 | goto __fail; |
92 | |
93 | if (r_ak4117) |
94 | *r_ak4117 = chip; |
95 | return 0; |
96 | |
97 | __fail: |
98 | snd_ak4117_free(chip); |
99 | return err; |
100 | } |
101 | |
102 | void snd_ak4117_reg_write(struct ak4117 *chip, unsigned char reg, unsigned char mask, unsigned char val) |
103 | { |
104 | if (reg >= 5) |
105 | return; |
106 | reg_write(ak4117: chip, reg, val: (chip->regmap[reg] & ~mask) | val); |
107 | } |
108 | |
109 | void snd_ak4117_reinit(struct ak4117 *chip) |
110 | { |
111 | unsigned char old = chip->regmap[AK4117_REG_PWRDN], reg; |
112 | |
113 | del_timer(timer: &chip->timer); |
114 | chip->init = 1; |
115 | /* bring the chip to reset state and powerdown state */ |
116 | reg_write(ak4117: chip, AK4117_REG_PWRDN, val: 0); |
117 | udelay(200); |
118 | /* release reset, but leave powerdown */ |
119 | reg_write(ak4117: chip, AK4117_REG_PWRDN, val: (old | AK4117_RST) & ~AK4117_PWN); |
120 | udelay(200); |
121 | for (reg = 1; reg < 5; reg++) |
122 | reg_write(ak4117: chip, reg, val: chip->regmap[reg]); |
123 | /* release powerdown, everything is initialized now */ |
124 | reg_write(ak4117: chip, AK4117_REG_PWRDN, val: old | AK4117_RST | AK4117_PWN); |
125 | chip->init = 0; |
126 | mod_timer(timer: &chip->timer, expires: 1 + jiffies); |
127 | } |
128 | |
129 | static unsigned int external_rate(unsigned char rcs1) |
130 | { |
131 | switch (rcs1 & (AK4117_FS0|AK4117_FS1|AK4117_FS2|AK4117_FS3)) { |
132 | case AK4117_FS_32000HZ: return 32000; |
133 | case AK4117_FS_44100HZ: return 44100; |
134 | case AK4117_FS_48000HZ: return 48000; |
135 | case AK4117_FS_88200HZ: return 88200; |
136 | case AK4117_FS_96000HZ: return 96000; |
137 | case AK4117_FS_176400HZ: return 176400; |
138 | case AK4117_FS_192000HZ: return 192000; |
139 | default: return 0; |
140 | } |
141 | } |
142 | |
143 | static int snd_ak4117_in_error_info(struct snd_kcontrol *kcontrol, |
144 | struct snd_ctl_elem_info *uinfo) |
145 | { |
146 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
147 | uinfo->count = 1; |
148 | uinfo->value.integer.min = 0; |
149 | uinfo->value.integer.max = LONG_MAX; |
150 | return 0; |
151 | } |
152 | |
153 | static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, |
154 | struct snd_ctl_elem_value *ucontrol) |
155 | { |
156 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
157 | |
158 | spin_lock_irq(lock: &chip->lock); |
159 | ucontrol->value.integer.value[0] = |
160 | chip->errors[kcontrol->private_value]; |
161 | chip->errors[kcontrol->private_value] = 0; |
162 | spin_unlock_irq(lock: &chip->lock); |
163 | return 0; |
164 | } |
165 | |
166 | #define snd_ak4117_in_bit_info snd_ctl_boolean_mono_info |
167 | |
168 | static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol, |
169 | struct snd_ctl_elem_value *ucontrol) |
170 | { |
171 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
172 | unsigned char reg = kcontrol->private_value & 0xff; |
173 | unsigned char bit = (kcontrol->private_value >> 8) & 0xff; |
174 | unsigned char inv = (kcontrol->private_value >> 31) & 1; |
175 | |
176 | ucontrol->value.integer.value[0] = ((reg_read(ak4117: chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; |
177 | return 0; |
178 | } |
179 | |
180 | static int snd_ak4117_rx_info(struct snd_kcontrol *kcontrol, |
181 | struct snd_ctl_elem_info *uinfo) |
182 | { |
183 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
184 | uinfo->count = 1; |
185 | uinfo->value.integer.min = 0; |
186 | uinfo->value.integer.max = 1; |
187 | return 0; |
188 | } |
189 | |
190 | static int snd_ak4117_rx_get(struct snd_kcontrol *kcontrol, |
191 | struct snd_ctl_elem_value *ucontrol) |
192 | { |
193 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
194 | |
195 | ucontrol->value.integer.value[0] = (chip->regmap[AK4117_REG_IO] & AK4117_IPS) ? 1 : 0; |
196 | return 0; |
197 | } |
198 | |
199 | static int snd_ak4117_rx_put(struct snd_kcontrol *kcontrol, |
200 | struct snd_ctl_elem_value *ucontrol) |
201 | { |
202 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
203 | int change; |
204 | u8 old_val; |
205 | |
206 | spin_lock_irq(lock: &chip->lock); |
207 | old_val = chip->regmap[AK4117_REG_IO]; |
208 | change = !!ucontrol->value.integer.value[0] != ((old_val & AK4117_IPS) ? 1 : 0); |
209 | if (change) |
210 | reg_write(ak4117: chip, AK4117_REG_IO, val: (old_val & ~AK4117_IPS) | (ucontrol->value.integer.value[0] ? AK4117_IPS : 0)); |
211 | spin_unlock_irq(lock: &chip->lock); |
212 | return change; |
213 | } |
214 | |
215 | static int snd_ak4117_rate_info(struct snd_kcontrol *kcontrol, |
216 | struct snd_ctl_elem_info *uinfo) |
217 | { |
218 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
219 | uinfo->count = 1; |
220 | uinfo->value.integer.min = 0; |
221 | uinfo->value.integer.max = 192000; |
222 | return 0; |
223 | } |
224 | |
225 | static int snd_ak4117_rate_get(struct snd_kcontrol *kcontrol, |
226 | struct snd_ctl_elem_value *ucontrol) |
227 | { |
228 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
229 | |
230 | ucontrol->value.integer.value[0] = external_rate(rcs1: reg_read(ak4117: chip, AK4117_REG_RCS1)); |
231 | return 0; |
232 | } |
233 | |
234 | static int snd_ak4117_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
235 | { |
236 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
237 | uinfo->count = 1; |
238 | return 0; |
239 | } |
240 | |
241 | static int snd_ak4117_spdif_get(struct snd_kcontrol *kcontrol, |
242 | struct snd_ctl_elem_value *ucontrol) |
243 | { |
244 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
245 | unsigned i; |
246 | |
247 | for (i = 0; i < AK4117_REG_RXCSB_SIZE; i++) |
248 | ucontrol->value.iec958.status[i] = reg_read(ak4117: chip, AK4117_REG_RXCSB0 + i); |
249 | return 0; |
250 | } |
251 | |
252 | static int snd_ak4117_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
253 | { |
254 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
255 | uinfo->count = 1; |
256 | return 0; |
257 | } |
258 | |
259 | static int snd_ak4117_spdif_mask_get(struct snd_kcontrol *kcontrol, |
260 | struct snd_ctl_elem_value *ucontrol) |
261 | { |
262 | memset(ucontrol->value.iec958.status, 0xff, AK4117_REG_RXCSB_SIZE); |
263 | return 0; |
264 | } |
265 | |
266 | static int snd_ak4117_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
267 | { |
268 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
269 | uinfo->value.integer.min = 0; |
270 | uinfo->value.integer.max = 0xffff; |
271 | uinfo->count = 4; |
272 | return 0; |
273 | } |
274 | |
275 | static int snd_ak4117_spdif_pget(struct snd_kcontrol *kcontrol, |
276 | struct snd_ctl_elem_value *ucontrol) |
277 | { |
278 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
279 | unsigned short tmp; |
280 | |
281 | ucontrol->value.integer.value[0] = 0xf8f2; |
282 | ucontrol->value.integer.value[1] = 0x4e1f; |
283 | tmp = reg_read(ak4117: chip, AK4117_REG_Pc0) | (reg_read(ak4117: chip, AK4117_REG_Pc1) << 8); |
284 | ucontrol->value.integer.value[2] = tmp; |
285 | tmp = reg_read(ak4117: chip, AK4117_REG_Pd0) | (reg_read(ak4117: chip, AK4117_REG_Pd1) << 8); |
286 | ucontrol->value.integer.value[3] = tmp; |
287 | return 0; |
288 | } |
289 | |
290 | static int snd_ak4117_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
291 | { |
292 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
293 | uinfo->count = AK4117_REG_QSUB_SIZE; |
294 | return 0; |
295 | } |
296 | |
297 | static int snd_ak4117_spdif_qget(struct snd_kcontrol *kcontrol, |
298 | struct snd_ctl_elem_value *ucontrol) |
299 | { |
300 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
301 | unsigned i; |
302 | |
303 | for (i = 0; i < AK4117_REG_QSUB_SIZE; i++) |
304 | ucontrol->value.bytes.data[i] = reg_read(ak4117: chip, AK4117_REG_QSUB_ADDR + i); |
305 | return 0; |
306 | } |
307 | |
308 | /* Don't forget to change AK4117_CONTROLS define!!! */ |
309 | static const struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { |
310 | { |
311 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
312 | .name = "IEC958 Parity Errors" , |
313 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
314 | .info = snd_ak4117_in_error_info, |
315 | .get = snd_ak4117_in_error_get, |
316 | .private_value = AK4117_PARITY_ERRORS, |
317 | }, |
318 | { |
319 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
320 | .name = "IEC958 V-Bit Errors" , |
321 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
322 | .info = snd_ak4117_in_error_info, |
323 | .get = snd_ak4117_in_error_get, |
324 | .private_value = AK4117_V_BIT_ERRORS, |
325 | }, |
326 | { |
327 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
328 | .name = "IEC958 C-CRC Errors" , |
329 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
330 | .info = snd_ak4117_in_error_info, |
331 | .get = snd_ak4117_in_error_get, |
332 | .private_value = AK4117_CCRC_ERRORS, |
333 | }, |
334 | { |
335 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
336 | .name = "IEC958 Q-CRC Errors" , |
337 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
338 | .info = snd_ak4117_in_error_info, |
339 | .get = snd_ak4117_in_error_get, |
340 | .private_value = AK4117_QCRC_ERRORS, |
341 | }, |
342 | { |
343 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
344 | .name = "IEC958 External Rate" , |
345 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
346 | .info = snd_ak4117_rate_info, |
347 | .get = snd_ak4117_rate_get, |
348 | }, |
349 | { |
350 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
351 | .name = SNDRV_CTL_NAME_IEC958("" ,CAPTURE,MASK), |
352 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
353 | .info = snd_ak4117_spdif_mask_info, |
354 | .get = snd_ak4117_spdif_mask_get, |
355 | }, |
356 | { |
357 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
358 | .name = SNDRV_CTL_NAME_IEC958("" ,CAPTURE,DEFAULT), |
359 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
360 | .info = snd_ak4117_spdif_info, |
361 | .get = snd_ak4117_spdif_get, |
362 | }, |
363 | { |
364 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
365 | .name = "IEC958 Preamble Capture Default" , |
366 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
367 | .info = snd_ak4117_spdif_pinfo, |
368 | .get = snd_ak4117_spdif_pget, |
369 | }, |
370 | { |
371 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
372 | .name = "IEC958 Q-subcode Capture Default" , |
373 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
374 | .info = snd_ak4117_spdif_qinfo, |
375 | .get = snd_ak4117_spdif_qget, |
376 | }, |
377 | { |
378 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
379 | .name = "IEC958 Audio" , |
380 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
381 | .info = snd_ak4117_in_bit_info, |
382 | .get = snd_ak4117_in_bit_get, |
383 | .private_value = (1<<31) | (3<<8) | AK4117_REG_RCS0, |
384 | }, |
385 | { |
386 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
387 | .name = "IEC958 Non-PCM Bitstream" , |
388 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
389 | .info = snd_ak4117_in_bit_info, |
390 | .get = snd_ak4117_in_bit_get, |
391 | .private_value = (5<<8) | AK4117_REG_RCS1, |
392 | }, |
393 | { |
394 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
395 | .name = "IEC958 DTS Bitstream" , |
396 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
397 | .info = snd_ak4117_in_bit_info, |
398 | .get = snd_ak4117_in_bit_get, |
399 | .private_value = (6<<8) | AK4117_REG_RCS1, |
400 | }, |
401 | { |
402 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
403 | .name = "AK4117 Input Select" , |
404 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, |
405 | .info = snd_ak4117_rx_info, |
406 | .get = snd_ak4117_rx_get, |
407 | .put = snd_ak4117_rx_put, |
408 | } |
409 | }; |
410 | |
411 | int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substream) |
412 | { |
413 | struct snd_kcontrol *kctl; |
414 | unsigned int idx; |
415 | int err; |
416 | |
417 | if (snd_BUG_ON(!cap_substream)) |
418 | return -EINVAL; |
419 | ak4117->substream = cap_substream; |
420 | for (idx = 0; idx < AK4117_CONTROLS; idx++) { |
421 | kctl = snd_ctl_new1(kcontrolnew: &snd_ak4117_iec958_controls[idx], private_data: ak4117); |
422 | if (kctl == NULL) |
423 | return -ENOMEM; |
424 | kctl->id.device = cap_substream->pcm->device; |
425 | kctl->id.subdevice = cap_substream->number; |
426 | err = snd_ctl_add(card: ak4117->card, kcontrol: kctl); |
427 | if (err < 0) |
428 | return err; |
429 | ak4117->kctls[idx] = kctl; |
430 | } |
431 | return 0; |
432 | } |
433 | |
434 | int snd_ak4117_external_rate(struct ak4117 *ak4117) |
435 | { |
436 | unsigned char rcs1; |
437 | |
438 | rcs1 = reg_read(ak4117, AK4117_REG_RCS1); |
439 | return external_rate(rcs1); |
440 | } |
441 | |
442 | int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) |
443 | { |
444 | struct snd_pcm_runtime *runtime = ak4117->substream ? ak4117->substream->runtime : NULL; |
445 | unsigned long _flags; |
446 | int res = 0; |
447 | unsigned char rcs0, rcs1, rcs2; |
448 | unsigned char c0, c1; |
449 | |
450 | rcs1 = reg_read(ak4117, AK4117_REG_RCS1); |
451 | if (flags & AK4117_CHECK_NO_STAT) |
452 | goto __rate; |
453 | rcs0 = reg_read(ak4117, AK4117_REG_RCS0); |
454 | rcs2 = reg_read(ak4117, AK4117_REG_RCS2); |
455 | // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); |
456 | spin_lock_irqsave(&ak4117->lock, _flags); |
457 | if (rcs0 & AK4117_PAR) |
458 | ak4117->errors[AK4117_PARITY_ERRORS]++; |
459 | if (rcs0 & AK4117_V) |
460 | ak4117->errors[AK4117_V_BIT_ERRORS]++; |
461 | if (rcs2 & AK4117_CCRC) |
462 | ak4117->errors[AK4117_CCRC_ERRORS]++; |
463 | if (rcs2 & AK4117_QCRC) |
464 | ak4117->errors[AK4117_QCRC_ERRORS]++; |
465 | c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ |
466 | (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); |
467 | c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ |
468 | (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)); |
469 | ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); |
470 | ak4117->rcs1 = rcs1; |
471 | ak4117->rcs2 = rcs2; |
472 | spin_unlock_irqrestore(lock: &ak4117->lock, flags: _flags); |
473 | |
474 | if (rcs0 & AK4117_PAR) |
475 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[0]->id); |
476 | if (rcs0 & AK4117_V) |
477 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[1]->id); |
478 | if (rcs2 & AK4117_CCRC) |
479 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[2]->id); |
480 | if (rcs2 & AK4117_QCRC) |
481 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[3]->id); |
482 | |
483 | /* rate change */ |
484 | if (c1 & 0x0f) |
485 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[4]->id); |
486 | |
487 | if ((c1 & AK4117_PEM) | (c0 & AK4117_CINT)) |
488 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[6]->id); |
489 | if (c0 & AK4117_QINT) |
490 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[8]->id); |
491 | |
492 | if (c0 & AK4117_AUDION) |
493 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[9]->id); |
494 | if (c1 & AK4117_NPCM) |
495 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[10]->id); |
496 | if (c1 & AK4117_DTSCD) |
497 | snd_ctl_notify(card: ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, id: &ak4117->kctls[11]->id); |
498 | |
499 | if (ak4117->change_callback && (c0 | c1) != 0) |
500 | ak4117->change_callback(ak4117, c0, c1); |
501 | |
502 | __rate: |
503 | /* compare rate */ |
504 | res = external_rate(rcs1); |
505 | if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) { |
506 | snd_pcm_stream_lock_irqsave(ak4117->substream, _flags); |
507 | if (snd_pcm_running(substream: ak4117->substream)) { |
508 | // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); |
509 | snd_pcm_stop(substream: ak4117->substream, SNDRV_PCM_STATE_DRAINING); |
510 | wake_up(&runtime->sleep); |
511 | res = 1; |
512 | } |
513 | snd_pcm_stream_unlock_irqrestore(substream: ak4117->substream, flags: _flags); |
514 | } |
515 | return res; |
516 | } |
517 | |
518 | static void snd_ak4117_timer(struct timer_list *t) |
519 | { |
520 | struct ak4117 *chip = from_timer(chip, t, timer); |
521 | |
522 | if (chip->init) |
523 | return; |
524 | snd_ak4117_check_rate_and_errors(ak4117: chip, flags: 0); |
525 | mod_timer(timer: &chip->timer, expires: 1 + jiffies); |
526 | } |
527 | |
528 | EXPORT_SYMBOL(snd_ak4117_create); |
529 | EXPORT_SYMBOL(snd_ak4117_reg_write); |
530 | EXPORT_SYMBOL(snd_ak4117_reinit); |
531 | EXPORT_SYMBOL(snd_ak4117_build); |
532 | EXPORT_SYMBOL(snd_ak4117_external_rate); |
533 | EXPORT_SYMBOL(snd_ak4117_check_rate_and_errors); |
534 | |