1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Routines for control of the AK4113 via I2C/4-wire serial interface |
4 | * IEC958 (S/PDIF) receiver by Asahi Kasei |
5 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
6 | * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com> |
7 | */ |
8 | |
9 | #include <linux/slab.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/module.h> |
12 | #include <sound/core.h> |
13 | #include <sound/control.h> |
14 | #include <sound/pcm.h> |
15 | #include <sound/ak4113.h> |
16 | #include <sound/asoundef.h> |
17 | #include <sound/info.h> |
18 | |
19 | MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>" ); |
20 | MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei" ); |
21 | MODULE_LICENSE("GPL" ); |
22 | |
23 | #define AK4113_ADDR 0x00 /* fixed address */ |
24 | |
25 | static void ak4113_stats(struct work_struct *work); |
26 | static void ak4113_init_regs(struct ak4113 *chip); |
27 | |
28 | |
29 | static void reg_write(struct ak4113 *ak4113, unsigned char reg, |
30 | unsigned char val) |
31 | { |
32 | ak4113->write(ak4113->private_data, reg, val); |
33 | if (reg < sizeof(ak4113->regmap)) |
34 | ak4113->regmap[reg] = val; |
35 | } |
36 | |
37 | static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) |
38 | { |
39 | return ak4113->read(ak4113->private_data, reg); |
40 | } |
41 | |
42 | static void snd_ak4113_free(struct ak4113 *chip) |
43 | { |
44 | atomic_inc(v: &chip->wq_processing); /* don't schedule new work */ |
45 | cancel_delayed_work_sync(dwork: &chip->work); |
46 | kfree(objp: chip); |
47 | } |
48 | |
49 | static int snd_ak4113_dev_free(struct snd_device *device) |
50 | { |
51 | struct ak4113 *chip = device->device_data; |
52 | snd_ak4113_free(chip); |
53 | return 0; |
54 | } |
55 | |
56 | int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, |
57 | ak4113_write_t *write, const unsigned char *pgm, |
58 | void *private_data, struct ak4113 **r_ak4113) |
59 | { |
60 | struct ak4113 *chip; |
61 | int err; |
62 | unsigned char reg; |
63 | static const struct snd_device_ops ops = { |
64 | .dev_free = snd_ak4113_dev_free, |
65 | }; |
66 | |
67 | chip = kzalloc(size: sizeof(*chip), GFP_KERNEL); |
68 | if (chip == NULL) |
69 | return -ENOMEM; |
70 | spin_lock_init(&chip->lock); |
71 | chip->card = card; |
72 | chip->read = read; |
73 | chip->write = write; |
74 | chip->private_data = private_data; |
75 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); |
76 | atomic_set(v: &chip->wq_processing, i: 0); |
77 | mutex_init(&chip->reinit_mutex); |
78 | |
79 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) |
80 | chip->regmap[reg] = pgm[reg]; |
81 | ak4113_init_regs(chip); |
82 | |
83 | chip->rcs0 = reg_read(ak4113: chip, AK4113_REG_RCS0) & ~(AK4113_QINT | |
84 | AK4113_CINT | AK4113_STC); |
85 | chip->rcs1 = reg_read(ak4113: chip, AK4113_REG_RCS1); |
86 | chip->rcs2 = reg_read(ak4113: chip, AK4113_REG_RCS2); |
87 | err = snd_device_new(card, type: SNDRV_DEV_CODEC, device_data: chip, ops: &ops); |
88 | if (err < 0) |
89 | goto __fail; |
90 | |
91 | if (r_ak4113) |
92 | *r_ak4113 = chip; |
93 | return 0; |
94 | |
95 | __fail: |
96 | snd_ak4113_free(chip); |
97 | return err; |
98 | } |
99 | EXPORT_SYMBOL_GPL(snd_ak4113_create); |
100 | |
101 | void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg, |
102 | unsigned char mask, unsigned char val) |
103 | { |
104 | if (reg >= AK4113_WRITABLE_REGS) |
105 | return; |
106 | reg_write(ak4113: chip, reg, val: (chip->regmap[reg] & ~mask) | val); |
107 | } |
108 | EXPORT_SYMBOL_GPL(snd_ak4113_reg_write); |
109 | |
110 | static void ak4113_init_regs(struct ak4113 *chip) |
111 | { |
112 | unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg; |
113 | |
114 | /* bring the chip to reset state and powerdown state */ |
115 | reg_write(ak4113: chip, AK4113_REG_PWRDN, val: old & ~(AK4113_RST|AK4113_PWN)); |
116 | udelay(200); |
117 | /* release reset, but leave powerdown */ |
118 | reg_write(ak4113: chip, AK4113_REG_PWRDN, val: (old | AK4113_RST) & ~AK4113_PWN); |
119 | udelay(200); |
120 | for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++) |
121 | reg_write(ak4113: chip, reg, val: chip->regmap[reg]); |
122 | /* release powerdown, everything is initialized now */ |
123 | reg_write(ak4113: chip, AK4113_REG_PWRDN, val: old | AK4113_RST | AK4113_PWN); |
124 | } |
125 | |
126 | void snd_ak4113_reinit(struct ak4113 *chip) |
127 | { |
128 | if (atomic_inc_return(v: &chip->wq_processing) == 1) |
129 | cancel_delayed_work_sync(dwork: &chip->work); |
130 | mutex_lock(&chip->reinit_mutex); |
131 | ak4113_init_regs(chip); |
132 | mutex_unlock(lock: &chip->reinit_mutex); |
133 | /* bring up statistics / event queing */ |
134 | if (atomic_dec_and_test(v: &chip->wq_processing)) |
135 | schedule_delayed_work(dwork: &chip->work, HZ / 10); |
136 | } |
137 | EXPORT_SYMBOL_GPL(snd_ak4113_reinit); |
138 | |
139 | static unsigned int external_rate(unsigned char rcs1) |
140 | { |
141 | switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) { |
142 | case AK4113_FS_8000HZ: |
143 | return 8000; |
144 | case AK4113_FS_11025HZ: |
145 | return 11025; |
146 | case AK4113_FS_16000HZ: |
147 | return 16000; |
148 | case AK4113_FS_22050HZ: |
149 | return 22050; |
150 | case AK4113_FS_24000HZ: |
151 | return 24000; |
152 | case AK4113_FS_32000HZ: |
153 | return 32000; |
154 | case AK4113_FS_44100HZ: |
155 | return 44100; |
156 | case AK4113_FS_48000HZ: |
157 | return 48000; |
158 | case AK4113_FS_64000HZ: |
159 | return 64000; |
160 | case AK4113_FS_88200HZ: |
161 | return 88200; |
162 | case AK4113_FS_96000HZ: |
163 | return 96000; |
164 | case AK4113_FS_176400HZ: |
165 | return 176400; |
166 | case AK4113_FS_192000HZ: |
167 | return 192000; |
168 | default: |
169 | return 0; |
170 | } |
171 | } |
172 | |
173 | static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol, |
174 | struct snd_ctl_elem_info *uinfo) |
175 | { |
176 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
177 | uinfo->count = 1; |
178 | uinfo->value.integer.min = 0; |
179 | uinfo->value.integer.max = LONG_MAX; |
180 | return 0; |
181 | } |
182 | |
183 | static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, |
184 | struct snd_ctl_elem_value *ucontrol) |
185 | { |
186 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
187 | |
188 | spin_lock_irq(lock: &chip->lock); |
189 | ucontrol->value.integer.value[0] = |
190 | chip->errors[kcontrol->private_value]; |
191 | chip->errors[kcontrol->private_value] = 0; |
192 | spin_unlock_irq(lock: &chip->lock); |
193 | return 0; |
194 | } |
195 | |
196 | #define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info |
197 | |
198 | static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol, |
199 | struct snd_ctl_elem_value *ucontrol) |
200 | { |
201 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
202 | unsigned char reg = kcontrol->private_value & 0xff; |
203 | unsigned char bit = (kcontrol->private_value >> 8) & 0xff; |
204 | unsigned char inv = (kcontrol->private_value >> 31) & 1; |
205 | |
206 | ucontrol->value.integer.value[0] = |
207 | ((reg_read(ak4113: chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; |
208 | return 0; |
209 | } |
210 | |
211 | static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol, |
212 | struct snd_ctl_elem_info *uinfo) |
213 | { |
214 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
215 | uinfo->count = 1; |
216 | uinfo->value.integer.min = 0; |
217 | uinfo->value.integer.max = 5; |
218 | return 0; |
219 | } |
220 | |
221 | static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol, |
222 | struct snd_ctl_elem_value *ucontrol) |
223 | { |
224 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
225 | |
226 | ucontrol->value.integer.value[0] = |
227 | (AK4113_IPS(chip->regmap[AK4113_REG_IO1])); |
228 | return 0; |
229 | } |
230 | |
231 | static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol, |
232 | struct snd_ctl_elem_value *ucontrol) |
233 | { |
234 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
235 | int change; |
236 | u8 old_val; |
237 | |
238 | spin_lock_irq(lock: &chip->lock); |
239 | old_val = chip->regmap[AK4113_REG_IO1]; |
240 | change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val); |
241 | if (change) |
242 | reg_write(ak4113: chip, AK4113_REG_IO1, |
243 | val: (old_val & (~AK4113_IPS(0xff))) | |
244 | (AK4113_IPS(ucontrol->value.integer.value[0]))); |
245 | spin_unlock_irq(lock: &chip->lock); |
246 | return change; |
247 | } |
248 | |
249 | static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol, |
250 | struct snd_ctl_elem_info *uinfo) |
251 | { |
252 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
253 | uinfo->count = 1; |
254 | uinfo->value.integer.min = 0; |
255 | uinfo->value.integer.max = 192000; |
256 | return 0; |
257 | } |
258 | |
259 | static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol, |
260 | struct snd_ctl_elem_value *ucontrol) |
261 | { |
262 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
263 | |
264 | ucontrol->value.integer.value[0] = external_rate(rcs1: reg_read(ak4113: chip, |
265 | AK4113_REG_RCS1)); |
266 | return 0; |
267 | } |
268 | |
269 | static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol, |
270 | struct snd_ctl_elem_info *uinfo) |
271 | { |
272 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
273 | uinfo->count = 1; |
274 | return 0; |
275 | } |
276 | |
277 | static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol, |
278 | struct snd_ctl_elem_value *ucontrol) |
279 | { |
280 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
281 | unsigned i; |
282 | |
283 | for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++) |
284 | ucontrol->value.iec958.status[i] = reg_read(ak4113: chip, |
285 | AK4113_REG_RXCSB0 + i); |
286 | return 0; |
287 | } |
288 | |
289 | static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol, |
290 | struct snd_ctl_elem_info *uinfo) |
291 | { |
292 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
293 | uinfo->count = 1; |
294 | return 0; |
295 | } |
296 | |
297 | static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol, |
298 | struct snd_ctl_elem_value *ucontrol) |
299 | { |
300 | memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE); |
301 | return 0; |
302 | } |
303 | |
304 | static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol, |
305 | struct snd_ctl_elem_info *uinfo) |
306 | { |
307 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
308 | uinfo->value.integer.min = 0; |
309 | uinfo->value.integer.max = 0xffff; |
310 | uinfo->count = 4; |
311 | return 0; |
312 | } |
313 | |
314 | static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol, |
315 | struct snd_ctl_elem_value *ucontrol) |
316 | { |
317 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
318 | unsigned short tmp; |
319 | |
320 | ucontrol->value.integer.value[0] = 0xf8f2; |
321 | ucontrol->value.integer.value[1] = 0x4e1f; |
322 | tmp = reg_read(ak4113: chip, AK4113_REG_Pc0) | |
323 | (reg_read(ak4113: chip, AK4113_REG_Pc1) << 8); |
324 | ucontrol->value.integer.value[2] = tmp; |
325 | tmp = reg_read(ak4113: chip, AK4113_REG_Pd0) | |
326 | (reg_read(ak4113: chip, AK4113_REG_Pd1) << 8); |
327 | ucontrol->value.integer.value[3] = tmp; |
328 | return 0; |
329 | } |
330 | |
331 | static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol, |
332 | struct snd_ctl_elem_info *uinfo) |
333 | { |
334 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
335 | uinfo->count = AK4113_REG_QSUB_SIZE; |
336 | return 0; |
337 | } |
338 | |
339 | static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol, |
340 | struct snd_ctl_elem_value *ucontrol) |
341 | { |
342 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
343 | unsigned i; |
344 | |
345 | for (i = 0; i < AK4113_REG_QSUB_SIZE; i++) |
346 | ucontrol->value.bytes.data[i] = reg_read(ak4113: chip, |
347 | AK4113_REG_QSUB_ADDR + i); |
348 | return 0; |
349 | } |
350 | |
351 | /* Don't forget to change AK4113_CONTROLS define!!! */ |
352 | static const struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { |
353 | { |
354 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
355 | .name = "IEC958 Parity Errors" , |
356 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
357 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
358 | .info = snd_ak4113_in_error_info, |
359 | .get = snd_ak4113_in_error_get, |
360 | .private_value = AK4113_PARITY_ERRORS, |
361 | }, |
362 | { |
363 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
364 | .name = "IEC958 V-Bit Errors" , |
365 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
366 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
367 | .info = snd_ak4113_in_error_info, |
368 | .get = snd_ak4113_in_error_get, |
369 | .private_value = AK4113_V_BIT_ERRORS, |
370 | }, |
371 | { |
372 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
373 | .name = "IEC958 C-CRC Errors" , |
374 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
375 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
376 | .info = snd_ak4113_in_error_info, |
377 | .get = snd_ak4113_in_error_get, |
378 | .private_value = AK4113_CCRC_ERRORS, |
379 | }, |
380 | { |
381 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
382 | .name = "IEC958 Q-CRC Errors" , |
383 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
384 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
385 | .info = snd_ak4113_in_error_info, |
386 | .get = snd_ak4113_in_error_get, |
387 | .private_value = AK4113_QCRC_ERRORS, |
388 | }, |
389 | { |
390 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
391 | .name = "IEC958 External Rate" , |
392 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
393 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
394 | .info = snd_ak4113_rate_info, |
395 | .get = snd_ak4113_rate_get, |
396 | }, |
397 | { |
398 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
399 | .name = SNDRV_CTL_NAME_IEC958("" , CAPTURE, MASK), |
400 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
401 | .info = snd_ak4113_spdif_mask_info, |
402 | .get = snd_ak4113_spdif_mask_get, |
403 | }, |
404 | { |
405 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
406 | .name = SNDRV_CTL_NAME_IEC958("" , CAPTURE, DEFAULT), |
407 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
408 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
409 | .info = snd_ak4113_spdif_info, |
410 | .get = snd_ak4113_spdif_get, |
411 | }, |
412 | { |
413 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
414 | .name = "IEC958 Preamble Capture Default" , |
415 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
416 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
417 | .info = snd_ak4113_spdif_pinfo, |
418 | .get = snd_ak4113_spdif_pget, |
419 | }, |
420 | { |
421 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
422 | .name = "IEC958 Q-subcode Capture Default" , |
423 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
424 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
425 | .info = snd_ak4113_spdif_qinfo, |
426 | .get = snd_ak4113_spdif_qget, |
427 | }, |
428 | { |
429 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
430 | .name = "IEC958 Audio" , |
431 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
432 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
433 | .info = snd_ak4113_in_bit_info, |
434 | .get = snd_ak4113_in_bit_get, |
435 | .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0, |
436 | }, |
437 | { |
438 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
439 | .name = "IEC958 Non-PCM Bitstream" , |
440 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
441 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
442 | .info = snd_ak4113_in_bit_info, |
443 | .get = snd_ak4113_in_bit_get, |
444 | .private_value = (0<<8) | AK4113_REG_RCS1, |
445 | }, |
446 | { |
447 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
448 | .name = "IEC958 DTS Bitstream" , |
449 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
450 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
451 | .info = snd_ak4113_in_bit_info, |
452 | .get = snd_ak4113_in_bit_get, |
453 | .private_value = (1<<8) | AK4113_REG_RCS1, |
454 | }, |
455 | { |
456 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
457 | .name = "AK4113 Input Select" , |
458 | .access = SNDRV_CTL_ELEM_ACCESS_READ | |
459 | SNDRV_CTL_ELEM_ACCESS_WRITE, |
460 | .info = snd_ak4113_rx_info, |
461 | .get = snd_ak4113_rx_get, |
462 | .put = snd_ak4113_rx_put, |
463 | } |
464 | }; |
465 | |
466 | static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry, |
467 | struct snd_info_buffer *buffer) |
468 | { |
469 | struct ak4113 *ak4113 = entry->private_data; |
470 | int reg, val; |
471 | /* all ak4113 registers 0x00 - 0x1c */ |
472 | for (reg = 0; reg < 0x1d; reg++) { |
473 | val = reg_read(ak4113, reg); |
474 | snd_iprintf(buffer, "0x%02x = 0x%02x\n" , reg, val); |
475 | } |
476 | } |
477 | |
478 | static void snd_ak4113_proc_init(struct ak4113 *ak4113) |
479 | { |
480 | snd_card_ro_proc_new(card: ak4113->card, name: "ak4113" , private_data: ak4113, |
481 | read: snd_ak4113_proc_regs_read); |
482 | } |
483 | |
484 | int snd_ak4113_build(struct ak4113 *ak4113, |
485 | struct snd_pcm_substream *cap_substream) |
486 | { |
487 | struct snd_kcontrol *kctl; |
488 | unsigned int idx; |
489 | int err; |
490 | |
491 | if (snd_BUG_ON(!cap_substream)) |
492 | return -EINVAL; |
493 | ak4113->substream = cap_substream; |
494 | for (idx = 0; idx < AK4113_CONTROLS; idx++) { |
495 | kctl = snd_ctl_new1(kcontrolnew: &snd_ak4113_iec958_controls[idx], private_data: ak4113); |
496 | if (kctl == NULL) |
497 | return -ENOMEM; |
498 | kctl->id.device = cap_substream->pcm->device; |
499 | kctl->id.subdevice = cap_substream->number; |
500 | err = snd_ctl_add(card: ak4113->card, kcontrol: kctl); |
501 | if (err < 0) |
502 | return err; |
503 | ak4113->kctls[idx] = kctl; |
504 | } |
505 | snd_ak4113_proc_init(ak4113); |
506 | /* trigger workq */ |
507 | schedule_delayed_work(dwork: &ak4113->work, HZ / 10); |
508 | return 0; |
509 | } |
510 | EXPORT_SYMBOL_GPL(snd_ak4113_build); |
511 | |
512 | int snd_ak4113_external_rate(struct ak4113 *ak4113) |
513 | { |
514 | unsigned char rcs1; |
515 | |
516 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); |
517 | return external_rate(rcs1); |
518 | } |
519 | EXPORT_SYMBOL_GPL(snd_ak4113_external_rate); |
520 | |
521 | int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) |
522 | { |
523 | struct snd_pcm_runtime *runtime = |
524 | ak4113->substream ? ak4113->substream->runtime : NULL; |
525 | unsigned long _flags; |
526 | int res = 0; |
527 | unsigned char rcs0, rcs1, rcs2; |
528 | unsigned char c0, c1; |
529 | |
530 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); |
531 | if (flags & AK4113_CHECK_NO_STAT) |
532 | goto __rate; |
533 | rcs0 = reg_read(ak4113, AK4113_REG_RCS0); |
534 | rcs2 = reg_read(ak4113, AK4113_REG_RCS2); |
535 | spin_lock_irqsave(&ak4113->lock, _flags); |
536 | if (rcs0 & AK4113_PAR) |
537 | ak4113->errors[AK4113_PARITY_ERRORS]++; |
538 | if (rcs0 & AK4113_V) |
539 | ak4113->errors[AK4113_V_BIT_ERRORS]++; |
540 | if (rcs2 & AK4113_CCRC) |
541 | ak4113->errors[AK4113_CCRC_ERRORS]++; |
542 | if (rcs2 & AK4113_QCRC) |
543 | ak4113->errors[AK4113_QCRC_ERRORS]++; |
544 | c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | |
545 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ |
546 | (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | |
547 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); |
548 | c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | |
549 | AK4113_DAT | 0xf0)) ^ |
550 | (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | |
551 | AK4113_DAT | 0xf0)); |
552 | ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); |
553 | ak4113->rcs1 = rcs1; |
554 | ak4113->rcs2 = rcs2; |
555 | spin_unlock_irqrestore(lock: &ak4113->lock, flags: _flags); |
556 | |
557 | if (rcs0 & AK4113_PAR) |
558 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
559 | id: &ak4113->kctls[0]->id); |
560 | if (rcs0 & AK4113_V) |
561 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
562 | id: &ak4113->kctls[1]->id); |
563 | if (rcs2 & AK4113_CCRC) |
564 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
565 | id: &ak4113->kctls[2]->id); |
566 | if (rcs2 & AK4113_QCRC) |
567 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
568 | id: &ak4113->kctls[3]->id); |
569 | |
570 | /* rate change */ |
571 | if (c1 & 0xf0) |
572 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
573 | id: &ak4113->kctls[4]->id); |
574 | |
575 | if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT)) |
576 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
577 | id: &ak4113->kctls[6]->id); |
578 | if (c0 & AK4113_QINT) |
579 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
580 | id: &ak4113->kctls[8]->id); |
581 | |
582 | if (c0 & AK4113_AUDION) |
583 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
584 | id: &ak4113->kctls[9]->id); |
585 | if (c1 & AK4113_NPCM) |
586 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
587 | id: &ak4113->kctls[10]->id); |
588 | if (c1 & AK4113_DTSCD) |
589 | snd_ctl_notify(card: ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, |
590 | id: &ak4113->kctls[11]->id); |
591 | |
592 | if (ak4113->change_callback && (c0 | c1) != 0) |
593 | ak4113->change_callback(ak4113, c0, c1); |
594 | |
595 | __rate: |
596 | /* compare rate */ |
597 | res = external_rate(rcs1); |
598 | if (!(flags & AK4113_CHECK_NO_RATE) && runtime && |
599 | (runtime->rate != res)) { |
600 | snd_pcm_stream_lock_irqsave(ak4113->substream, _flags); |
601 | if (snd_pcm_running(substream: ak4113->substream)) { |
602 | /*printk(KERN_DEBUG "rate changed (%i <- %i)\n", |
603 | * runtime->rate, res); */ |
604 | snd_pcm_stop(substream: ak4113->substream, |
605 | SNDRV_PCM_STATE_DRAINING); |
606 | wake_up(&runtime->sleep); |
607 | res = 1; |
608 | } |
609 | snd_pcm_stream_unlock_irqrestore(substream: ak4113->substream, flags: _flags); |
610 | } |
611 | return res; |
612 | } |
613 | EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors); |
614 | |
615 | static void ak4113_stats(struct work_struct *work) |
616 | { |
617 | struct ak4113 *chip = container_of(work, struct ak4113, work.work); |
618 | |
619 | if (atomic_inc_return(v: &chip->wq_processing) == 1) |
620 | snd_ak4113_check_rate_and_errors(chip, chip->check_flags); |
621 | |
622 | if (atomic_dec_and_test(v: &chip->wq_processing)) |
623 | schedule_delayed_work(dwork: &chip->work, HZ / 10); |
624 | } |
625 | |
626 | #ifdef CONFIG_PM |
627 | void snd_ak4113_suspend(struct ak4113 *chip) |
628 | { |
629 | atomic_inc(v: &chip->wq_processing); /* don't schedule new work */ |
630 | cancel_delayed_work_sync(dwork: &chip->work); |
631 | } |
632 | EXPORT_SYMBOL(snd_ak4113_suspend); |
633 | |
634 | void snd_ak4113_resume(struct ak4113 *chip) |
635 | { |
636 | atomic_dec(v: &chip->wq_processing); |
637 | snd_ak4113_reinit(chip); |
638 | } |
639 | EXPORT_SYMBOL(snd_ak4113_resume); |
640 | #endif |
641 | |