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 static void snd_ak4117_free(struct ak4117 *chip) 38 { 39 timer_shutdown_sync(&chip->timer); 40 kfree(chip); 41 } 42 43 static 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 50 int 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 91 void 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 98 void snd_ak4117_reinit(struct ak4117 *chip) 99 { 100 unsigned char old = chip->regmap[AK4117_REG_PWRDN], reg; 101 102 del_timer(&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 118 static 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 132 static 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 142 static 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 spin_lock_irq(&chip->lock); 148 ucontrol->value.integer.value[0] = 149 chip->errors[kcontrol->private_value]; 150 chip->errors[kcontrol->private_value] = 0; 151 spin_unlock_irq(&chip->lock); 152 return 0; 153 } 154 155 #define snd_ak4117_in_bit_info snd_ctl_boolean_mono_info 156 157 static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol, 158 struct snd_ctl_elem_value *ucontrol) 159 { 160 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 161 unsigned char reg = kcontrol->private_value & 0xff; 162 unsigned char bit = (kcontrol->private_value >> 8) & 0xff; 163 unsigned char inv = (kcontrol->private_value >> 31) & 1; 164 165 ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; 166 return 0; 167 } 168 169 static int snd_ak4117_rx_info(struct snd_kcontrol *kcontrol, 170 struct snd_ctl_elem_info *uinfo) 171 { 172 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 173 uinfo->count = 1; 174 uinfo->value.integer.min = 0; 175 uinfo->value.integer.max = 1; 176 return 0; 177 } 178 179 static int snd_ak4117_rx_get(struct snd_kcontrol *kcontrol, 180 struct snd_ctl_elem_value *ucontrol) 181 { 182 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 183 184 ucontrol->value.integer.value[0] = (chip->regmap[AK4117_REG_IO] & AK4117_IPS) ? 1 : 0; 185 return 0; 186 } 187 188 static int snd_ak4117_rx_put(struct snd_kcontrol *kcontrol, 189 struct snd_ctl_elem_value *ucontrol) 190 { 191 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 192 int change; 193 u8 old_val; 194 195 spin_lock_irq(&chip->lock); 196 old_val = chip->regmap[AK4117_REG_IO]; 197 change = !!ucontrol->value.integer.value[0] != ((old_val & AK4117_IPS) ? 1 : 0); 198 if (change) 199 reg_write(chip, AK4117_REG_IO, (old_val & ~AK4117_IPS) | (ucontrol->value.integer.value[0] ? AK4117_IPS : 0)); 200 spin_unlock_irq(&chip->lock); 201 return change; 202 } 203 204 static int snd_ak4117_rate_info(struct snd_kcontrol *kcontrol, 205 struct snd_ctl_elem_info *uinfo) 206 { 207 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 208 uinfo->count = 1; 209 uinfo->value.integer.min = 0; 210 uinfo->value.integer.max = 192000; 211 return 0; 212 } 213 214 static int snd_ak4117_rate_get(struct snd_kcontrol *kcontrol, 215 struct snd_ctl_elem_value *ucontrol) 216 { 217 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 218 219 ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4117_REG_RCS1)); 220 return 0; 221 } 222 223 static int snd_ak4117_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 224 { 225 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 226 uinfo->count = 1; 227 return 0; 228 } 229 230 static int snd_ak4117_spdif_get(struct snd_kcontrol *kcontrol, 231 struct snd_ctl_elem_value *ucontrol) 232 { 233 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 234 unsigned i; 235 236 for (i = 0; i < AK4117_REG_RXCSB_SIZE; i++) 237 ucontrol->value.iec958.status[i] = reg_read(chip, AK4117_REG_RXCSB0 + i); 238 return 0; 239 } 240 241 static int snd_ak4117_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 242 { 243 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 244 uinfo->count = 1; 245 return 0; 246 } 247 248 static int snd_ak4117_spdif_mask_get(struct snd_kcontrol *kcontrol, 249 struct snd_ctl_elem_value *ucontrol) 250 { 251 memset(ucontrol->value.iec958.status, 0xff, AK4117_REG_RXCSB_SIZE); 252 return 0; 253 } 254 255 static int snd_ak4117_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 256 { 257 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 258 uinfo->value.integer.min = 0; 259 uinfo->value.integer.max = 0xffff; 260 uinfo->count = 4; 261 return 0; 262 } 263 264 static int snd_ak4117_spdif_pget(struct snd_kcontrol *kcontrol, 265 struct snd_ctl_elem_value *ucontrol) 266 { 267 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 268 unsigned short tmp; 269 270 ucontrol->value.integer.value[0] = 0xf8f2; 271 ucontrol->value.integer.value[1] = 0x4e1f; 272 tmp = reg_read(chip, AK4117_REG_Pc0) | (reg_read(chip, AK4117_REG_Pc1) << 8); 273 ucontrol->value.integer.value[2] = tmp; 274 tmp = reg_read(chip, AK4117_REG_Pd0) | (reg_read(chip, AK4117_REG_Pd1) << 8); 275 ucontrol->value.integer.value[3] = tmp; 276 return 0; 277 } 278 279 static int snd_ak4117_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 280 { 281 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 282 uinfo->count = AK4117_REG_QSUB_SIZE; 283 return 0; 284 } 285 286 static int snd_ak4117_spdif_qget(struct snd_kcontrol *kcontrol, 287 struct snd_ctl_elem_value *ucontrol) 288 { 289 struct ak4117 *chip = snd_kcontrol_chip(kcontrol); 290 unsigned i; 291 292 for (i = 0; i < AK4117_REG_QSUB_SIZE; i++) 293 ucontrol->value.bytes.data[i] = reg_read(chip, AK4117_REG_QSUB_ADDR + i); 294 return 0; 295 } 296 297 /* Don't forget to change AK4117_CONTROLS define!!! */ 298 static const struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { 299 { 300 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 301 .name = "IEC958 Parity Errors", 302 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 303 .info = snd_ak4117_in_error_info, 304 .get = snd_ak4117_in_error_get, 305 .private_value = AK4117_PARITY_ERRORS, 306 }, 307 { 308 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 309 .name = "IEC958 V-Bit Errors", 310 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 311 .info = snd_ak4117_in_error_info, 312 .get = snd_ak4117_in_error_get, 313 .private_value = AK4117_V_BIT_ERRORS, 314 }, 315 { 316 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 317 .name = "IEC958 C-CRC Errors", 318 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 319 .info = snd_ak4117_in_error_info, 320 .get = snd_ak4117_in_error_get, 321 .private_value = AK4117_CCRC_ERRORS, 322 }, 323 { 324 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 325 .name = "IEC958 Q-CRC Errors", 326 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 327 .info = snd_ak4117_in_error_info, 328 .get = snd_ak4117_in_error_get, 329 .private_value = AK4117_QCRC_ERRORS, 330 }, 331 { 332 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 333 .name = "IEC958 External Rate", 334 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 335 .info = snd_ak4117_rate_info, 336 .get = snd_ak4117_rate_get, 337 }, 338 { 339 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 340 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), 341 .access = SNDRV_CTL_ELEM_ACCESS_READ, 342 .info = snd_ak4117_spdif_mask_info, 343 .get = snd_ak4117_spdif_mask_get, 344 }, 345 { 346 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 347 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), 348 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 349 .info = snd_ak4117_spdif_info, 350 .get = snd_ak4117_spdif_get, 351 }, 352 { 353 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 354 .name = "IEC958 Preamble Capture Default", 355 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 356 .info = snd_ak4117_spdif_pinfo, 357 .get = snd_ak4117_spdif_pget, 358 }, 359 { 360 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 361 .name = "IEC958 Q-subcode Capture Default", 362 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 363 .info = snd_ak4117_spdif_qinfo, 364 .get = snd_ak4117_spdif_qget, 365 }, 366 { 367 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 368 .name = "IEC958 Audio", 369 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 370 .info = snd_ak4117_in_bit_info, 371 .get = snd_ak4117_in_bit_get, 372 .private_value = (1<<31) | (3<<8) | AK4117_REG_RCS0, 373 }, 374 { 375 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 376 .name = "IEC958 Non-PCM Bitstream", 377 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 378 .info = snd_ak4117_in_bit_info, 379 .get = snd_ak4117_in_bit_get, 380 .private_value = (5<<8) | AK4117_REG_RCS1, 381 }, 382 { 383 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 384 .name = "IEC958 DTS Bitstream", 385 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 386 .info = snd_ak4117_in_bit_info, 387 .get = snd_ak4117_in_bit_get, 388 .private_value = (6<<8) | AK4117_REG_RCS1, 389 }, 390 { 391 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 392 .name = "AK4117 Input Select", 393 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, 394 .info = snd_ak4117_rx_info, 395 .get = snd_ak4117_rx_get, 396 .put = snd_ak4117_rx_put, 397 } 398 }; 399 400 int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substream) 401 { 402 struct snd_kcontrol *kctl; 403 unsigned int idx; 404 int err; 405 406 if (snd_BUG_ON(!cap_substream)) 407 return -EINVAL; 408 ak4117->substream = cap_substream; 409 for (idx = 0; idx < AK4117_CONTROLS; idx++) { 410 kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117); 411 if (kctl == NULL) 412 return -ENOMEM; 413 kctl->id.device = cap_substream->pcm->device; 414 kctl->id.subdevice = cap_substream->number; 415 err = snd_ctl_add(ak4117->card, kctl); 416 if (err < 0) 417 return err; 418 ak4117->kctls[idx] = kctl; 419 } 420 return 0; 421 } 422 423 int snd_ak4117_external_rate(struct ak4117 *ak4117) 424 { 425 unsigned char rcs1; 426 427 rcs1 = reg_read(ak4117, AK4117_REG_RCS1); 428 return external_rate(rcs1); 429 } 430 431 int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) 432 { 433 struct snd_pcm_runtime *runtime = ak4117->substream ? ak4117->substream->runtime : NULL; 434 unsigned long _flags; 435 int res = 0; 436 unsigned char rcs0, rcs1, rcs2; 437 unsigned char c0, c1; 438 439 rcs1 = reg_read(ak4117, AK4117_REG_RCS1); 440 if (flags & AK4117_CHECK_NO_STAT) 441 goto __rate; 442 rcs0 = reg_read(ak4117, AK4117_REG_RCS0); 443 rcs2 = reg_read(ak4117, AK4117_REG_RCS2); 444 spin_lock_irqsave(&ak4117->lock, _flags); 445 if (rcs0 & AK4117_PAR) 446 ak4117->errors[AK4117_PARITY_ERRORS]++; 447 if (rcs0 & AK4117_V) 448 ak4117->errors[AK4117_V_BIT_ERRORS]++; 449 if (rcs2 & AK4117_CCRC) 450 ak4117->errors[AK4117_CCRC_ERRORS]++; 451 if (rcs2 & AK4117_QCRC) 452 ak4117->errors[AK4117_QCRC_ERRORS]++; 453 c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ 454 (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); 455 c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ 456 (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)); 457 ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); 458 ak4117->rcs1 = rcs1; 459 ak4117->rcs2 = rcs2; 460 spin_unlock_irqrestore(&ak4117->lock, _flags); 461 462 if (rcs0 & AK4117_PAR) 463 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[0]->id); 464 if (rcs0 & AK4117_V) 465 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[1]->id); 466 if (rcs2 & AK4117_CCRC) 467 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[2]->id); 468 if (rcs2 & AK4117_QCRC) 469 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[3]->id); 470 471 /* rate change */ 472 if (c1 & 0x0f) 473 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[4]->id); 474 475 if ((c1 & AK4117_PEM) | (c0 & AK4117_CINT)) 476 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[6]->id); 477 if (c0 & AK4117_QINT) 478 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[8]->id); 479 480 if (c0 & AK4117_AUDION) 481 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[9]->id); 482 if (c1 & AK4117_NPCM) 483 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[10]->id); 484 if (c1 & AK4117_DTSCD) 485 snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[11]->id); 486 487 if (ak4117->change_callback && (c0 | c1) != 0) 488 ak4117->change_callback(ak4117, c0, c1); 489 490 __rate: 491 /* compare rate */ 492 res = external_rate(rcs1); 493 if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) { 494 snd_pcm_stream_lock_irqsave(ak4117->substream, _flags); 495 if (snd_pcm_running(ak4117->substream)) { 496 snd_pcm_stop(ak4117->substream, SNDRV_PCM_STATE_DRAINING); 497 wake_up(&runtime->sleep); 498 res = 1; 499 } 500 snd_pcm_stream_unlock_irqrestore(ak4117->substream, _flags); 501 } 502 return res; 503 } 504 505 static void snd_ak4117_timer(struct timer_list *t) 506 { 507 struct ak4117 *chip = from_timer(chip, t, timer); 508 509 if (chip->init) 510 return; 511 snd_ak4117_check_rate_and_errors(chip, 0); 512 mod_timer(&chip->timer, 1 + jiffies); 513 } 514 515 EXPORT_SYMBOL(snd_ak4117_create); 516 EXPORT_SYMBOL(snd_ak4117_reg_write); 517 EXPORT_SYMBOL(snd_ak4117_reinit); 518 EXPORT_SYMBOL(snd_ak4117_build); 519 EXPORT_SYMBOL(snd_ak4117_external_rate); 520 EXPORT_SYMBOL(snd_ak4117_check_rate_and_errors); 521