Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'topic/ak411x-fix' into for-next

+82 -28
+10 -1
include/sound/ak4113.h
··· 286 286 ak4113_write_t *write; 287 287 ak4113_read_t *read; 288 288 void *private_data; 289 - unsigned int init:1; 289 + atomic_t wq_processing; 290 + struct mutex reinit_mutex; 290 291 spinlock_t lock; 291 292 unsigned char regmap[AK4113_WRITABLE_REGS]; 292 293 struct snd_kcontrol *kctls[AK4113_CONTROLS]; ··· 317 316 struct snd_pcm_substream *capture_substream); 318 317 int snd_ak4113_external_rate(struct ak4113 *ak4113); 319 318 int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags); 319 + 320 + #ifdef CONFIG_PM 321 + void snd_ak4113_suspend(struct ak4113 *chip); 322 + void snd_ak4113_resume(struct ak4113 *chip); 323 + #else 324 + static inline void snd_ak4113_suspend(struct ak4113 *chip) {} 325 + static inline void snd_ak4113_resume(struct ak4113 *chip) {} 326 + #endif 320 327 321 328 #endif /* __SOUND_AK4113_H */ 322 329
+10 -1
include/sound/ak4114.h
··· 168 168 ak4114_write_t * write; 169 169 ak4114_read_t * read; 170 170 void * private_data; 171 - unsigned int init: 1; 171 + atomic_t wq_processing; 172 + struct mutex reinit_mutex; 172 173 spinlock_t lock; 173 174 unsigned char regmap[6]; 174 175 unsigned char txcsb[5]; ··· 199 198 struct snd_pcm_substream *capture_substream); 200 199 int snd_ak4114_external_rate(struct ak4114 *ak4114); 201 200 int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags); 201 + 202 + #ifdef CONFIG_PM 203 + void snd_ak4114_suspend(struct ak4114 *chip); 204 + void snd_ak4114_resume(struct ak4114 *chip); 205 + #else 206 + static inline void snd_ak4114_suspend(struct ak4114 *chip) {} 207 + static inline void snd_ak4114_resume(struct ak4114 *chip) {} 208 + #endif 202 209 203 210 #endif /* __SOUND_AK4114_H */ 204 211
+27 -9
sound/i2c/other/ak4113.c
··· 56 56 57 57 static void snd_ak4113_free(struct ak4113 *chip) 58 58 { 59 - chip->init = 1; /* don't schedule new work */ 60 - mb(); 59 + atomic_inc(&chip->wq_processing); /* don't schedule new work */ 61 60 cancel_delayed_work_sync(&chip->work); 62 61 kfree(chip); 63 62 } ··· 88 89 chip->write = write; 89 90 chip->private_data = private_data; 90 91 INIT_DELAYED_WORK(&chip->work, ak4113_stats); 92 + atomic_set(&chip->wq_processing, 0); 93 + mutex_init(&chip->reinit_mutex); 91 94 92 95 for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) 93 96 chip->regmap[reg] = pgm[reg]; ··· 140 139 141 140 void snd_ak4113_reinit(struct ak4113 *chip) 142 141 { 143 - chip->init = 1; 144 - mb(); 145 - flush_delayed_work(&chip->work); 142 + if (atomic_inc_return(&chip->wq_processing) == 1) 143 + cancel_delayed_work_sync(&chip->work); 144 + mutex_lock(&chip->reinit_mutex); 146 145 ak4113_init_regs(chip); 146 + mutex_unlock(&chip->reinit_mutex); 147 147 /* bring up statistics / event queing */ 148 - chip->init = 0; 149 - if (chip->kctls[0]) 148 + if (atomic_dec_and_test(&chip->wq_processing)) 150 149 schedule_delayed_work(&chip->work, HZ / 10); 151 150 } 152 151 EXPORT_SYMBOL_GPL(snd_ak4113_reinit); ··· 633 632 { 634 633 struct ak4113 *chip = container_of(work, struct ak4113, work.work); 635 634 636 - if (!chip->init) 635 + if (atomic_inc_return(&chip->wq_processing) == 1) 637 636 snd_ak4113_check_rate_and_errors(chip, chip->check_flags); 638 637 639 - schedule_delayed_work(&chip->work, HZ / 10); 638 + if (atomic_dec_and_test(&chip->wq_processing)) 639 + schedule_delayed_work(&chip->work, HZ / 10); 640 640 } 641 + 642 + #ifdef CONFIG_PM 643 + void snd_ak4113_suspend(struct ak4113 *chip) 644 + { 645 + atomic_inc(&chip->wq_processing); /* don't schedule new work */ 646 + cancel_delayed_work_sync(&chip->work); 647 + } 648 + EXPORT_SYMBOL(snd_ak4113_suspend); 649 + 650 + void snd_ak4113_resume(struct ak4113 *chip) 651 + { 652 + atomic_dec(&chip->wq_processing); 653 + snd_ak4113_reinit(chip); 654 + } 655 + EXPORT_SYMBOL(snd_ak4113_resume); 656 + #endif
+32 -16
sound/i2c/other/ak4114.c
··· 66 66 67 67 static void snd_ak4114_free(struct ak4114 *chip) 68 68 { 69 - chip->init = 1; /* don't schedule new work */ 70 - mb(); 69 + atomic_inc(&chip->wq_processing); /* don't schedule new work */ 71 70 cancel_delayed_work_sync(&chip->work); 72 71 kfree(chip); 73 72 } ··· 99 100 chip->write = write; 100 101 chip->private_data = private_data; 101 102 INIT_DELAYED_WORK(&chip->work, ak4114_stats); 103 + atomic_set(&chip->wq_processing, 0); 104 + mutex_init(&chip->reinit_mutex); 102 105 103 106 for (reg = 0; reg < 6; reg++) 104 107 chip->regmap[reg] = pgm[reg]; ··· 123 122 snd_ak4114_free(chip); 124 123 return err < 0 ? err : -EIO; 125 124 } 125 + EXPORT_SYMBOL(snd_ak4114_create); 126 126 127 127 void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) 128 128 { ··· 133 131 reg_write(chip, reg, 134 132 (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); 135 133 } 134 + EXPORT_SYMBOL(snd_ak4114_reg_write); 136 135 137 136 static void ak4114_init_regs(struct ak4114 *chip) 138 137 { ··· 155 152 156 153 void snd_ak4114_reinit(struct ak4114 *chip) 157 154 { 158 - chip->init = 1; 159 - mb(); 160 - flush_delayed_work(&chip->work); 155 + if (atomic_inc_return(&chip->wq_processing) == 1) 156 + cancel_delayed_work_sync(&chip->work); 157 + mutex_lock(&chip->reinit_mutex); 161 158 ak4114_init_regs(chip); 159 + mutex_unlock(&chip->reinit_mutex); 162 160 /* bring up statistics / event queing */ 163 - chip->init = 0; 164 - if (chip->kctls[0]) 161 + if (atomic_dec_and_test(&chip->wq_processing)) 165 162 schedule_delayed_work(&chip->work, HZ / 10); 166 163 } 164 + EXPORT_SYMBOL(snd_ak4114_reinit); 167 165 168 166 static unsigned int external_rate(unsigned char rcs1) 169 167 { ··· 509 505 schedule_delayed_work(&ak4114->work, HZ / 10); 510 506 return 0; 511 507 } 508 + EXPORT_SYMBOL(snd_ak4114_build); 512 509 513 510 /* notify kcontrols if any parameters are changed */ 514 511 static void ak4114_notify(struct ak4114 *ak4114, ··· 565 560 rcs1 = reg_read(ak4114, AK4114_REG_RCS1); 566 561 return external_rate(rcs1); 567 562 } 563 + EXPORT_SYMBOL(snd_ak4114_external_rate); 568 564 569 565 int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) 570 566 { ··· 613 607 } 614 608 return res; 615 609 } 610 + EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); 616 611 617 612 static void ak4114_stats(struct work_struct *work) 618 613 { 619 614 struct ak4114 *chip = container_of(work, struct ak4114, work.work); 620 615 621 - if (!chip->init) 616 + if (atomic_inc_return(&chip->wq_processing) == 1) 622 617 snd_ak4114_check_rate_and_errors(chip, chip->check_flags); 623 - 624 - schedule_delayed_work(&chip->work, HZ / 10); 618 + if (atomic_dec_and_test(&chip->wq_processing)) 619 + schedule_delayed_work(&chip->work, HZ / 10); 625 620 } 626 621 627 - EXPORT_SYMBOL(snd_ak4114_create); 628 - EXPORT_SYMBOL(snd_ak4114_reg_write); 629 - EXPORT_SYMBOL(snd_ak4114_reinit); 630 - EXPORT_SYMBOL(snd_ak4114_build); 631 - EXPORT_SYMBOL(snd_ak4114_external_rate); 632 - EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); 622 + #ifdef CONFIG_PM 623 + void snd_ak4114_suspend(struct ak4114 *chip) 624 + { 625 + atomic_inc(&chip->wq_processing); /* don't schedule new work */ 626 + cancel_delayed_work_sync(&chip->work); 627 + } 628 + EXPORT_SYMBOL(snd_ak4114_suspend); 629 + 630 + void snd_ak4114_resume(struct ak4114 *chip) 631 + { 632 + atomic_dec(&chip->wq_processing); 633 + snd_ak4114_reinit(chip); 634 + } 635 + EXPORT_SYMBOL(snd_ak4114_resume); 636 + #endif
+3 -1
sound/pci/ice1712/juli.c
··· 491 491 /* akm4358 un-reset, un-mute */ 492 492 snd_akm4xxx_reset(ak, 0); 493 493 /* reinit ak4114 */ 494 - snd_ak4114_reinit(spec->ak4114); 494 + snd_ak4114_resume(spec->ak4114); 495 495 return 0; 496 496 } 497 497 498 498 static int juli_suspend(struct snd_ice1712 *ice) 499 499 { 500 500 struct snd_akm4xxx *ak = ice->akm; 501 + struct juli_spec *spec = ice->spec; 501 502 /* akm4358 reset and soft-mute */ 502 503 snd_akm4xxx_reset(ak, 1); 504 + snd_ak4114_suspend(spec->ak4114); 503 505 return 0; 504 506 } 505 507 #endif