diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-01-28 16:32:10 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-28 16:32:10 -0500 |
commit | d832f3dcb6e2d153fbb69b91931058d138bc41cb (patch) | |
tree | b58210600b92bbe0c20c02724a47068682b99d5e /sound | |
parent | 5da7f924a41949797875c98a776dca1737a0f372 (diff) | |
parent | 1781e78c63317c04e6ae6a076acfd53236f420bc (diff) |
Merge branch 'topic/ak411x-fix' into for-next
Diffstat (limited to 'sound')
-rw-r--r-- | sound/i2c/other/ak4113.c | 36 | ||||
-rw-r--r-- | sound/i2c/other/ak4114.c | 46 | ||||
-rw-r--r-- | sound/pci/ice1712/juli.c | 4 |
3 files changed, 61 insertions, 25 deletions
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index 1a3a6fa27158..88844881cbff 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c | |||
@@ -56,8 +56,7 @@ static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) | |||
56 | 56 | ||
57 | static void snd_ak4113_free(struct ak4113 *chip) | 57 | static void snd_ak4113_free(struct ak4113 *chip) |
58 | { | 58 | { |
59 | chip->init = 1; /* don't schedule new work */ | 59 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ |
60 | mb(); | ||
61 | cancel_delayed_work_sync(&chip->work); | 60 | cancel_delayed_work_sync(&chip->work); |
62 | kfree(chip); | 61 | kfree(chip); |
63 | } | 62 | } |
@@ -89,6 +88,8 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, | |||
89 | chip->write = write; | 88 | chip->write = write; |
90 | chip->private_data = private_data; | 89 | chip->private_data = private_data; |
91 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); | 90 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); |
91 | atomic_set(&chip->wq_processing, 0); | ||
92 | mutex_init(&chip->reinit_mutex); | ||
92 | 93 | ||
93 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) | 94 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) |
94 | chip->regmap[reg] = pgm[reg]; | 95 | chip->regmap[reg] = pgm[reg]; |
@@ -139,13 +140,13 @@ static void ak4113_init_regs(struct ak4113 *chip) | |||
139 | 140 | ||
140 | void snd_ak4113_reinit(struct ak4113 *chip) | 141 | void snd_ak4113_reinit(struct ak4113 *chip) |
141 | { | 142 | { |
142 | chip->init = 1; | 143 | if (atomic_inc_return(&chip->wq_processing) == 1) |
143 | mb(); | 144 | cancel_delayed_work_sync(&chip->work); |
144 | flush_delayed_work(&chip->work); | 145 | mutex_lock(&chip->reinit_mutex); |
145 | ak4113_init_regs(chip); | 146 | ak4113_init_regs(chip); |
147 | mutex_unlock(&chip->reinit_mutex); | ||
146 | /* bring up statistics / event queing */ | 148 | /* bring up statistics / event queing */ |
147 | chip->init = 0; | 149 | if (atomic_dec_and_test(&chip->wq_processing)) |
148 | if (chip->kctls[0]) | ||
149 | schedule_delayed_work(&chip->work, HZ / 10); | 150 | schedule_delayed_work(&chip->work, HZ / 10); |
150 | } | 151 | } |
151 | EXPORT_SYMBOL_GPL(snd_ak4113_reinit); | 152 | EXPORT_SYMBOL_GPL(snd_ak4113_reinit); |
@@ -632,8 +633,25 @@ static void ak4113_stats(struct work_struct *work) | |||
632 | { | 633 | { |
633 | struct ak4113 *chip = container_of(work, struct ak4113, work.work); | 634 | struct ak4113 *chip = container_of(work, struct ak4113, work.work); |
634 | 635 | ||
635 | if (!chip->init) | 636 | if (atomic_inc_return(&chip->wq_processing) == 1) |
636 | snd_ak4113_check_rate_and_errors(chip, chip->check_flags); | 637 | snd_ak4113_check_rate_and_errors(chip, chip->check_flags); |
637 | 638 | ||
638 | schedule_delayed_work(&chip->work, HZ / 10); | 639 | if (atomic_dec_and_test(&chip->wq_processing)) |
640 | schedule_delayed_work(&chip->work, HZ / 10); | ||
641 | } | ||
642 | |||
643 | #ifdef CONFIG_PM | ||
644 | void snd_ak4113_suspend(struct ak4113 *chip) | ||
645 | { | ||
646 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ | ||
647 | cancel_delayed_work_sync(&chip->work); | ||
648 | } | ||
649 | EXPORT_SYMBOL(snd_ak4113_suspend); | ||
650 | |||
651 | void snd_ak4113_resume(struct ak4113 *chip) | ||
652 | { | ||
653 | atomic_dec(&chip->wq_processing); | ||
654 | snd_ak4113_reinit(chip); | ||
639 | } | 655 | } |
656 | EXPORT_SYMBOL(snd_ak4113_resume); | ||
657 | #endif | ||
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index c7f56339415d..5a4cf3fab4ae 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -66,8 +66,7 @@ static void reg_dump(struct ak4114 *ak4114) | |||
66 | 66 | ||
67 | static void snd_ak4114_free(struct ak4114 *chip) | 67 | static void snd_ak4114_free(struct ak4114 *chip) |
68 | { | 68 | { |
69 | chip->init = 1; /* don't schedule new work */ | 69 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ |
70 | mb(); | ||
71 | cancel_delayed_work_sync(&chip->work); | 70 | cancel_delayed_work_sync(&chip->work); |
72 | kfree(chip); | 71 | kfree(chip); |
73 | } | 72 | } |
@@ -100,6 +99,8 @@ int snd_ak4114_create(struct snd_card *card, | |||
100 | chip->write = write; | 99 | chip->write = write; |
101 | chip->private_data = private_data; | 100 | chip->private_data = private_data; |
102 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); | 101 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); |
102 | atomic_set(&chip->wq_processing, 0); | ||
103 | mutex_init(&chip->reinit_mutex); | ||
103 | 104 | ||
104 | for (reg = 0; reg < 6; reg++) | 105 | for (reg = 0; reg < 6; reg++) |
105 | chip->regmap[reg] = pgm[reg]; | 106 | chip->regmap[reg] = pgm[reg]; |
@@ -122,6 +123,7 @@ int snd_ak4114_create(struct snd_card *card, | |||
122 | snd_ak4114_free(chip); | 123 | snd_ak4114_free(chip); |
123 | return err < 0 ? err : -EIO; | 124 | return err < 0 ? err : -EIO; |
124 | } | 125 | } |
126 | EXPORT_SYMBOL(snd_ak4114_create); | ||
125 | 127 | ||
126 | void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) | 128 | void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) |
127 | { | 129 | { |
@@ -131,6 +133,7 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char | |||
131 | reg_write(chip, reg, | 133 | reg_write(chip, reg, |
132 | (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); | 134 | (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); |
133 | } | 135 | } |
136 | EXPORT_SYMBOL(snd_ak4114_reg_write); | ||
134 | 137 | ||
135 | static void ak4114_init_regs(struct ak4114 *chip) | 138 | static void ak4114_init_regs(struct ak4114 *chip) |
136 | { | 139 | { |
@@ -152,15 +155,16 @@ static void ak4114_init_regs(struct ak4114 *chip) | |||
152 | 155 | ||
153 | void snd_ak4114_reinit(struct ak4114 *chip) | 156 | void snd_ak4114_reinit(struct ak4114 *chip) |
154 | { | 157 | { |
155 | chip->init = 1; | 158 | if (atomic_inc_return(&chip->wq_processing) == 1) |
156 | mb(); | 159 | cancel_delayed_work_sync(&chip->work); |
157 | flush_delayed_work(&chip->work); | 160 | mutex_lock(&chip->reinit_mutex); |
158 | ak4114_init_regs(chip); | 161 | ak4114_init_regs(chip); |
162 | mutex_unlock(&chip->reinit_mutex); | ||
159 | /* bring up statistics / event queing */ | 163 | /* bring up statistics / event queing */ |
160 | chip->init = 0; | 164 | if (atomic_dec_and_test(&chip->wq_processing)) |
161 | if (chip->kctls[0]) | ||
162 | schedule_delayed_work(&chip->work, HZ / 10); | 165 | schedule_delayed_work(&chip->work, HZ / 10); |
163 | } | 166 | } |
167 | EXPORT_SYMBOL(snd_ak4114_reinit); | ||
164 | 168 | ||
165 | static unsigned int external_rate(unsigned char rcs1) | 169 | static unsigned int external_rate(unsigned char rcs1) |
166 | { | 170 | { |
@@ -505,6 +509,7 @@ int snd_ak4114_build(struct ak4114 *ak4114, | |||
505 | schedule_delayed_work(&ak4114->work, HZ / 10); | 509 | schedule_delayed_work(&ak4114->work, HZ / 10); |
506 | return 0; | 510 | return 0; |
507 | } | 511 | } |
512 | EXPORT_SYMBOL(snd_ak4114_build); | ||
508 | 513 | ||
509 | /* notify kcontrols if any parameters are changed */ | 514 | /* notify kcontrols if any parameters are changed */ |
510 | static void ak4114_notify(struct ak4114 *ak4114, | 515 | static void ak4114_notify(struct ak4114 *ak4114, |
@@ -560,6 +565,7 @@ int snd_ak4114_external_rate(struct ak4114 *ak4114) | |||
560 | rcs1 = reg_read(ak4114, AK4114_REG_RCS1); | 565 | rcs1 = reg_read(ak4114, AK4114_REG_RCS1); |
561 | return external_rate(rcs1); | 566 | return external_rate(rcs1); |
562 | } | 567 | } |
568 | EXPORT_SYMBOL(snd_ak4114_external_rate); | ||
563 | 569 | ||
564 | int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) | 570 | int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) |
565 | { | 571 | { |
@@ -607,20 +613,30 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) | |||
607 | } | 613 | } |
608 | return res; | 614 | return res; |
609 | } | 615 | } |
616 | EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); | ||
610 | 617 | ||
611 | static void ak4114_stats(struct work_struct *work) | 618 | static void ak4114_stats(struct work_struct *work) |
612 | { | 619 | { |
613 | struct ak4114 *chip = container_of(work, struct ak4114, work.work); | 620 | struct ak4114 *chip = container_of(work, struct ak4114, work.work); |
614 | 621 | ||
615 | if (!chip->init) | 622 | if (atomic_inc_return(&chip->wq_processing) == 1) |
616 | snd_ak4114_check_rate_and_errors(chip, chip->check_flags); | 623 | snd_ak4114_check_rate_and_errors(chip, chip->check_flags); |
624 | if (atomic_dec_and_test(&chip->wq_processing)) | ||
625 | schedule_delayed_work(&chip->work, HZ / 10); | ||
626 | } | ||
617 | 627 | ||
618 | schedule_delayed_work(&chip->work, HZ / 10); | 628 | #ifdef CONFIG_PM |
629 | void snd_ak4114_suspend(struct ak4114 *chip) | ||
630 | { | ||
631 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ | ||
632 | cancel_delayed_work_sync(&chip->work); | ||
619 | } | 633 | } |
634 | EXPORT_SYMBOL(snd_ak4114_suspend); | ||
620 | 635 | ||
621 | EXPORT_SYMBOL(snd_ak4114_create); | 636 | void snd_ak4114_resume(struct ak4114 *chip) |
622 | EXPORT_SYMBOL(snd_ak4114_reg_write); | 637 | { |
623 | EXPORT_SYMBOL(snd_ak4114_reinit); | 638 | atomic_dec(&chip->wq_processing); |
624 | EXPORT_SYMBOL(snd_ak4114_build); | 639 | snd_ak4114_reinit(chip); |
625 | EXPORT_SYMBOL(snd_ak4114_external_rate); | 640 | } |
626 | EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); | 641 | EXPORT_SYMBOL(snd_ak4114_resume); |
642 | #endif | ||
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index a1536c1a7ed4..4f0213427152 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -491,15 +491,17 @@ static int juli_resume(struct snd_ice1712 *ice) | |||
491 | /* akm4358 un-reset, un-mute */ | 491 | /* akm4358 un-reset, un-mute */ |
492 | snd_akm4xxx_reset(ak, 0); | 492 | snd_akm4xxx_reset(ak, 0); |
493 | /* reinit ak4114 */ | 493 | /* reinit ak4114 */ |
494 | snd_ak4114_reinit(spec->ak4114); | 494 | snd_ak4114_resume(spec->ak4114); |
495 | return 0; | 495 | return 0; |
496 | } | 496 | } |
497 | 497 | ||
498 | static int juli_suspend(struct snd_ice1712 *ice) | 498 | static int juli_suspend(struct snd_ice1712 *ice) |
499 | { | 499 | { |
500 | struct snd_akm4xxx *ak = ice->akm; | 500 | struct snd_akm4xxx *ak = ice->akm; |
501 | struct juli_spec *spec = ice->spec; | ||
501 | /* akm4358 reset and soft-mute */ | 502 | /* akm4358 reset and soft-mute */ |
502 | snd_akm4xxx_reset(ak, 1); | 503 | snd_akm4xxx_reset(ak, 1); |
504 | snd_ak4114_suspend(spec->ak4114); | ||
503 | return 0; | 505 | return 0; |
504 | } | 506 | } |
505 | #endif | 507 | #endif |