1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Routines for control of the AK4114 via I2C and 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/ak4114.h> 15 #include <sound/asoundef.h> 16 #include <sound/info.h> 17 18 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 19 MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei"); 20 MODULE_LICENSE("GPL"); 21 22 #define AK4114_ADDR 0x00 /* fixed address */ 23 24 static void ak4114_stats(struct work_struct *work); 25 static void ak4114_init_regs(struct ak4114 *chip); 26 27 static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) 28 { 29 ak4114->write(ak4114->private_data, reg, val); 30 if (reg <= AK4114_REG_INT1_MASK) 31 ak4114->regmap[reg] = val; 32 else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) 33 ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val; 34 } 35 36 static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) 37 { 38 return ak4114->read(ak4114->private_data, reg); 39 } 40 41 #if 0 42 static void reg_dump(struct ak4114 *ak4114) 43 { 44 int i; 45 46 printk(KERN_DEBUG "AK4114 REG DUMP:\n"); 47 for (i = 0; i < 0x20; i++) 48 printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < ARRAY_SIZE(ak4114->regmap) ? ak4114->regmap[i] : 0); 49 } 50 #endif 51 52 static void snd_ak4114_free(struct ak4114 *chip) 53 { 54 atomic_inc(&chip->wq_processing); /* don't schedule new work */ 55 cancel_delayed_work_sync(&chip->work); 56 kfree(chip); 57 } 58 59 static int snd_ak4114_dev_free(struct snd_device *device) 60 { 61 struct ak4114 *chip = device->device_data; 62 snd_ak4114_free(chip); 63 return 0; 64 } 65 66 int snd_ak4114_create(struct snd_card *card, 67 ak4114_read_t *read, ak4114_write_t *write, 68 const unsigned char pgm[6], const unsigned char txcsb[5], 69 void *private_data, struct ak4114 **r_ak4114) 70 { 71 struct ak4114 *chip; 72 int err = 0; 73 unsigned char reg; 74 static const struct snd_device_ops ops = { 75 .dev_free = snd_ak4114_dev_free, 76 }; 77 78 chip = kzalloc(sizeof(*chip), GFP_KERNEL); 79 if (chip == NULL) 80 return -ENOMEM; 81 spin_lock_init(&chip->lock); 82 chip->card = card; 83 chip->read = read; 84 chip->write = write; 85 chip->private_data = private_data; 86 INIT_DELAYED_WORK(&chip->work, ak4114_stats); 87 atomic_set(&chip->wq_processing, 0); 88 mutex_init(&chip->reinit_mutex); 89 90 for (reg = 0; reg < 6; reg++) 91 chip->regmap[reg] = pgm[reg]; 92 for (reg = 0; reg < 5; reg++) 93 chip->txcsb[reg] = txcsb[reg]; 94 95 ak4114_init_regs(chip); 96 97 chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); 98 chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); 99 100 err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops); 101 if (err < 0) 102 goto __fail; 103 104 if (r_ak4114) 105 *r_ak4114 = chip; 106 return 0; 107 108 __fail: 109 snd_ak4114_free(chip); 110 return err; 111 } 112 EXPORT_SYMBOL(snd_ak4114_create); 113 114 void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) 115 { 116 if (reg <= AK4114_REG_INT1_MASK) 117 reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); 118 else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) 119 reg_write(chip, reg, 120 (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); 121 } 122 EXPORT_SYMBOL(snd_ak4114_reg_write); 123 124 static void ak4114_init_regs(struct ak4114 *chip) 125 { 126 unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg; 127 128 /* bring the chip to reset state and powerdown state */ 129 reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); 130 udelay(200); 131 /* release reset, but leave powerdown */ 132 reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN); 133 udelay(200); 134 for (reg = 1; reg < 6; reg++) 135 reg_write(chip, reg, chip->regmap[reg]); 136 for (reg = 0; reg < 5; reg++) 137 reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]); 138 /* release powerdown, everything is initialized now */ 139 reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); 140 } 141 142 void snd_ak4114_reinit(struct ak4114 *chip) 143 { 144 if (atomic_inc_return(&chip->wq_processing) == 1) 145 cancel_delayed_work_sync(&chip->work); 146 mutex_lock(&chip->reinit_mutex); 147 ak4114_init_regs(chip); 148 mutex_unlock(&chip->reinit_mutex); 149 /* bring up statistics / event queing */ 150 if (atomic_dec_and_test(&chip->wq_processing)) 151 schedule_delayed_work(&chip->work, HZ / 10); 152 } 153 EXPORT_SYMBOL(snd_ak4114_reinit); 154 155 static unsigned int external_rate(unsigned char rcs1) 156 { 157 switch (rcs1 & (AK4114_FS0|AK4114_FS1|AK4114_FS2|AK4114_FS3)) { 158 case AK4114_FS_32000HZ: return 32000; 159 case AK4114_FS_44100HZ: return 44100; 160 case AK4114_FS_48000HZ: return 48000; 161 case AK4114_FS_88200HZ: return 88200; 162 case AK4114_FS_96000HZ: return 96000; 163 case AK4114_FS_176400HZ: return 176400; 164 case AK4114_FS_192000HZ: return 192000; 165 default: return 0; 166 } 167 } 168 169 static int snd_ak4114_in_error_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 = LONG_MAX; 176 return 0; 177 } 178 179 static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, 180 struct snd_ctl_elem_value *ucontrol) 181 { 182 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 183 184 spin_lock_irq(&chip->lock); 185 ucontrol->value.integer.value[0] = 186 chip->errors[kcontrol->private_value]; 187 chip->errors[kcontrol->private_value] = 0; 188 spin_unlock_irq(&chip->lock); 189 return 0; 190 } 191 192 #define snd_ak4114_in_bit_info snd_ctl_boolean_mono_info 193 194 static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol, 195 struct snd_ctl_elem_value *ucontrol) 196 { 197 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 198 unsigned char reg = kcontrol->private_value & 0xff; 199 unsigned char bit = (kcontrol->private_value >> 8) & 0xff; 200 unsigned char inv = (kcontrol->private_value >> 31) & 1; 201 202 ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; 203 return 0; 204 } 205 206 static int snd_ak4114_rate_info(struct snd_kcontrol *kcontrol, 207 struct snd_ctl_elem_info *uinfo) 208 { 209 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 210 uinfo->count = 1; 211 uinfo->value.integer.min = 0; 212 uinfo->value.integer.max = 192000; 213 return 0; 214 } 215 216 static int snd_ak4114_rate_get(struct snd_kcontrol *kcontrol, 217 struct snd_ctl_elem_value *ucontrol) 218 { 219 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 220 221 ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1)); 222 return 0; 223 } 224 225 static int snd_ak4114_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 226 { 227 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 228 uinfo->count = 1; 229 return 0; 230 } 231 232 static int snd_ak4114_spdif_get(struct snd_kcontrol *kcontrol, 233 struct snd_ctl_elem_value *ucontrol) 234 { 235 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 236 unsigned i; 237 238 for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++) 239 ucontrol->value.iec958.status[i] = reg_read(chip, AK4114_REG_RXCSB0 + i); 240 return 0; 241 } 242 243 static int snd_ak4114_spdif_playback_get(struct snd_kcontrol *kcontrol, 244 struct snd_ctl_elem_value *ucontrol) 245 { 246 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 247 unsigned i; 248 249 for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) 250 ucontrol->value.iec958.status[i] = chip->txcsb[i]; 251 return 0; 252 } 253 254 static int snd_ak4114_spdif_playback_put(struct snd_kcontrol *kcontrol, 255 struct snd_ctl_elem_value *ucontrol) 256 { 257 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 258 unsigned i; 259 260 for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) 261 reg_write(chip, AK4114_REG_TXCSB0 + i, ucontrol->value.iec958.status[i]); 262 return 0; 263 } 264 265 static int snd_ak4114_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 266 { 267 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 268 uinfo->count = 1; 269 return 0; 270 } 271 272 static int snd_ak4114_spdif_mask_get(struct snd_kcontrol *kcontrol, 273 struct snd_ctl_elem_value *ucontrol) 274 { 275 memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE); 276 return 0; 277 } 278 279 static int snd_ak4114_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 280 { 281 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 282 uinfo->value.integer.min = 0; 283 uinfo->value.integer.max = 0xffff; 284 uinfo->count = 4; 285 return 0; 286 } 287 288 static int snd_ak4114_spdif_pget(struct snd_kcontrol *kcontrol, 289 struct snd_ctl_elem_value *ucontrol) 290 { 291 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 292 unsigned short tmp; 293 294 ucontrol->value.integer.value[0] = 0xf8f2; 295 ucontrol->value.integer.value[1] = 0x4e1f; 296 tmp = reg_read(chip, AK4114_REG_Pc0) | (reg_read(chip, AK4114_REG_Pc1) << 8); 297 ucontrol->value.integer.value[2] = tmp; 298 tmp = reg_read(chip, AK4114_REG_Pd0) | (reg_read(chip, AK4114_REG_Pd1) << 8); 299 ucontrol->value.integer.value[3] = tmp; 300 return 0; 301 } 302 303 static int snd_ak4114_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 304 { 305 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 306 uinfo->count = AK4114_REG_QSUB_SIZE; 307 return 0; 308 } 309 310 static int snd_ak4114_spdif_qget(struct snd_kcontrol *kcontrol, 311 struct snd_ctl_elem_value *ucontrol) 312 { 313 struct ak4114 *chip = snd_kcontrol_chip(kcontrol); 314 unsigned i; 315 316 for (i = 0; i < AK4114_REG_QSUB_SIZE; i++) 317 ucontrol->value.bytes.data[i] = reg_read(chip, AK4114_REG_QSUB_ADDR + i); 318 return 0; 319 } 320 321 /* Don't forget to change AK4114_CONTROLS define!!! */ 322 static const struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { 323 { 324 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 325 .name = "IEC958 Parity Errors", 326 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 327 .info = snd_ak4114_in_error_info, 328 .get = snd_ak4114_in_error_get, 329 .private_value = AK4114_PARITY_ERRORS, 330 }, 331 { 332 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 333 .name = "IEC958 V-Bit Errors", 334 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 335 .info = snd_ak4114_in_error_info, 336 .get = snd_ak4114_in_error_get, 337 .private_value = AK4114_V_BIT_ERRORS, 338 }, 339 { 340 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 341 .name = "IEC958 C-CRC Errors", 342 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 343 .info = snd_ak4114_in_error_info, 344 .get = snd_ak4114_in_error_get, 345 .private_value = AK4114_CCRC_ERRORS, 346 }, 347 { 348 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 349 .name = "IEC958 Q-CRC Errors", 350 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 351 .info = snd_ak4114_in_error_info, 352 .get = snd_ak4114_in_error_get, 353 .private_value = AK4114_QCRC_ERRORS, 354 }, 355 { 356 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 357 .name = "IEC958 External Rate", 358 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 359 .info = snd_ak4114_rate_info, 360 .get = snd_ak4114_rate_get, 361 }, 362 { 363 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 364 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), 365 .access = SNDRV_CTL_ELEM_ACCESS_READ, 366 .info = snd_ak4114_spdif_mask_info, 367 .get = snd_ak4114_spdif_mask_get, 368 }, 369 { 370 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 371 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 372 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 373 .info = snd_ak4114_spdif_info, 374 .get = snd_ak4114_spdif_playback_get, 375 .put = snd_ak4114_spdif_playback_put, 376 }, 377 { 378 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 379 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), 380 .access = SNDRV_CTL_ELEM_ACCESS_READ, 381 .info = snd_ak4114_spdif_mask_info, 382 .get = snd_ak4114_spdif_mask_get, 383 }, 384 { 385 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 386 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), 387 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 388 .info = snd_ak4114_spdif_info, 389 .get = snd_ak4114_spdif_get, 390 }, 391 { 392 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 393 .name = "IEC958 Preamble Capture Default", 394 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 395 .info = snd_ak4114_spdif_pinfo, 396 .get = snd_ak4114_spdif_pget, 397 }, 398 { 399 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 400 .name = "IEC958 Q-subcode Capture Default", 401 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 402 .info = snd_ak4114_spdif_qinfo, 403 .get = snd_ak4114_spdif_qget, 404 }, 405 { 406 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 407 .name = "IEC958 Audio", 408 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 409 .info = snd_ak4114_in_bit_info, 410 .get = snd_ak4114_in_bit_get, 411 .private_value = (1<<31) | (1<<8) | AK4114_REG_RCS0, 412 }, 413 { 414 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 415 .name = "IEC958 Non-PCM Bitstream", 416 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 417 .info = snd_ak4114_in_bit_info, 418 .get = snd_ak4114_in_bit_get, 419 .private_value = (6<<8) | AK4114_REG_RCS0, 420 }, 421 { 422 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 423 .name = "IEC958 DTS Bitstream", 424 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 425 .info = snd_ak4114_in_bit_info, 426 .get = snd_ak4114_in_bit_get, 427 .private_value = (3<<8) | AK4114_REG_RCS0, 428 }, 429 { 430 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 431 .name = "IEC958 PPL Lock Status", 432 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 433 .info = snd_ak4114_in_bit_info, 434 .get = snd_ak4114_in_bit_get, 435 .private_value = (1<<31) | (4<<8) | AK4114_REG_RCS0, 436 } 437 }; 438 439 440 static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry, 441 struct snd_info_buffer *buffer) 442 { 443 struct ak4114 *ak4114 = entry->private_data; 444 int reg, val; 445 /* all ak4114 registers 0x00 - 0x1f */ 446 for (reg = 0; reg < 0x20; reg++) { 447 val = reg_read(ak4114, reg); 448 snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); 449 } 450 } 451 452 static void snd_ak4114_proc_init(struct ak4114 *ak4114) 453 { 454 snd_card_ro_proc_new(ak4114->card, "ak4114", ak4114, 455 snd_ak4114_proc_regs_read); 456 } 457 458 int snd_ak4114_build(struct ak4114 *ak4114, 459 struct snd_pcm_substream *ply_substream, 460 struct snd_pcm_substream *cap_substream) 461 { 462 struct snd_kcontrol *kctl; 463 unsigned int idx; 464 int err; 465 466 if (snd_BUG_ON(!cap_substream)) 467 return -EINVAL; 468 ak4114->playback_substream = ply_substream; 469 ak4114->capture_substream = cap_substream; 470 for (idx = 0; idx < AK4114_CONTROLS; idx++) { 471 kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); 472 if (kctl == NULL) 473 return -ENOMEM; 474 if (strstr(kctl->id.name, "Playback")) { 475 if (ply_substream == NULL) { 476 snd_ctl_free_one(kctl); 477 ak4114->kctls[idx] = NULL; 478 continue; 479 } 480 kctl->id.device = ply_substream->pcm->device; 481 kctl->id.subdevice = ply_substream->number; 482 } else { 483 kctl->id.device = cap_substream->pcm->device; 484 kctl->id.subdevice = cap_substream->number; 485 } 486 err = snd_ctl_add(ak4114->card, kctl); 487 if (err < 0) 488 return err; 489 ak4114->kctls[idx] = kctl; 490 } 491 snd_ak4114_proc_init(ak4114); 492 /* trigger workq */ 493 schedule_delayed_work(&ak4114->work, HZ / 10); 494 return 0; 495 } 496 EXPORT_SYMBOL(snd_ak4114_build); 497 498 /* notify kcontrols if any parameters are changed */ 499 static void ak4114_notify(struct ak4114 *ak4114, 500 unsigned char rcs0, unsigned char rcs1, 501 unsigned char c0, unsigned char c1) 502 { 503 if (!ak4114->kctls[0]) 504 return; 505 506 if (rcs0 & AK4114_PAR) 507 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 508 &ak4114->kctls[0]->id); 509 if (rcs0 & AK4114_V) 510 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 511 &ak4114->kctls[1]->id); 512 if (rcs1 & AK4114_CCRC) 513 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 514 &ak4114->kctls[2]->id); 515 if (rcs1 & AK4114_QCRC) 516 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 517 &ak4114->kctls[3]->id); 518 519 /* rate change */ 520 if (c1 & 0xf0) 521 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 522 &ak4114->kctls[4]->id); 523 524 if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT)) 525 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 526 &ak4114->kctls[9]->id); 527 if (c0 & AK4114_QINT) 528 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 529 &ak4114->kctls[10]->id); 530 531 if (c0 & AK4114_AUDION) 532 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 533 &ak4114->kctls[11]->id); 534 if (c0 & AK4114_AUTO) 535 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 536 &ak4114->kctls[12]->id); 537 if (c0 & AK4114_DTSCD) 538 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 539 &ak4114->kctls[13]->id); 540 if (c0 & AK4114_UNLCK) 541 snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, 542 &ak4114->kctls[14]->id); 543 } 544 545 int snd_ak4114_external_rate(struct ak4114 *ak4114) 546 { 547 unsigned char rcs1; 548 549 rcs1 = reg_read(ak4114, AK4114_REG_RCS1); 550 return external_rate(rcs1); 551 } 552 EXPORT_SYMBOL(snd_ak4114_external_rate); 553 554 int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) 555 { 556 struct snd_pcm_runtime *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL; 557 unsigned long _flags; 558 int res = 0; 559 unsigned char rcs0, rcs1; 560 unsigned char c0, c1; 561 562 rcs1 = reg_read(ak4114, AK4114_REG_RCS1); 563 if (flags & AK4114_CHECK_NO_STAT) 564 goto __rate; 565 rcs0 = reg_read(ak4114, AK4114_REG_RCS0); 566 spin_lock_irqsave(&ak4114->lock, _flags); 567 if (rcs0 & AK4114_PAR) 568 ak4114->errors[AK4114_PARITY_ERRORS]++; 569 if (rcs1 & AK4114_V) 570 ak4114->errors[AK4114_V_BIT_ERRORS]++; 571 if (rcs1 & AK4114_CCRC) 572 ak4114->errors[AK4114_CCRC_ERRORS]++; 573 if (rcs1 & AK4114_QCRC) 574 ak4114->errors[AK4114_QCRC_ERRORS]++; 575 c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ 576 (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); 577 c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); 578 ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT); 579 ak4114->rcs1 = rcs1; 580 spin_unlock_irqrestore(&ak4114->lock, _flags); 581 582 ak4114_notify(ak4114, rcs0, rcs1, c0, c1); 583 if (ak4114->change_callback && (c0 | c1) != 0) 584 ak4114->change_callback(ak4114, c0, c1); 585 586 __rate: 587 /* compare rate */ 588 res = external_rate(rcs1); 589 if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) { 590 snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags); 591 if (snd_pcm_running(ak4114->capture_substream)) { 592 // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); 593 snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); 594 res = 1; 595 } 596 snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); 597 } 598 return res; 599 } 600 EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); 601 602 static void ak4114_stats(struct work_struct *work) 603 { 604 struct ak4114 *chip = container_of(work, struct ak4114, work.work); 605 606 if (atomic_inc_return(&chip->wq_processing) == 1) 607 snd_ak4114_check_rate_and_errors(chip, chip->check_flags); 608 if (atomic_dec_and_test(&chip->wq_processing)) 609 schedule_delayed_work(&chip->work, HZ / 10); 610 } 611 612 #ifdef CONFIG_PM 613 void snd_ak4114_suspend(struct ak4114 *chip) 614 { 615 atomic_inc(&chip->wq_processing); /* don't schedule new work */ 616 cancel_delayed_work_sync(&chip->work); 617 } 618 EXPORT_SYMBOL(snd_ak4114_suspend); 619 620 void snd_ak4114_resume(struct ak4114 *chip) 621 { 622 atomic_dec(&chip->wq_processing); 623 snd_ak4114_reinit(chip); 624 } 625 EXPORT_SYMBOL(snd_ak4114_resume); 626 #endif 627
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.