File Index
Files and directories
Sign in
FILE

ak4117.c

File preview with syntax highlighting.

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