aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-09-19 15:20:17 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 10:50:59 -0400
commitfe1b5e874dad88646d344b092d3066cb21b279eb (patch)
treed5181520c738565f2481b5e3e2eaae1cc6a152ff
parentb438f817b16eec5b497fe78cc2b889f3276e6508 (diff)
[ALSA] ad1848: simplify MCE down code
The polling loop to check for ACI to go down was more convoluted than it needed to be. New loop should be more efficient and it is a lot simpler. The old loop checked for a timeout before checking for ACI down, which could result in an erroneous timeout. It's only a failure if the timeout expires _and_ ACI is still high. There is nothing wrong with the timeout expiring while the task is sleeping if ACI went low. A polling loop to check for the device to leaving INIT mode is removed. The device must have already left init for the previous ACI loop to have finished. Acked-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r--sound/isa/ad1848/ad1848_lib.c57
1 files changed, 21 insertions, 36 deletions
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 18355fd66cb5..21536b7de608 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -203,9 +203,8 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
203 203
204static void snd_ad1848_mce_down(struct snd_ad1848 *chip) 204static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
205{ 205{
206 unsigned long flags; 206 unsigned long flags, timeout;
207 int timeout; 207 int reg;
208 unsigned long end_time;
209 208
210 spin_lock_irqsave(&chip->reg_lock, flags); 209 spin_lock_irqsave(&chip->reg_lock, flags);
211 for (timeout = 5; timeout > 0; timeout--) 210 for (timeout = 5; timeout > 0; timeout--)
@@ -222,50 +221,36 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
222#endif 221#endif
223 222
224 chip->mce_bit &= ~AD1848_MCE; 223 chip->mce_bit &= ~AD1848_MCE;
225 timeout = inb(AD1848P(chip, REGSEL)); 224 reg = inb(AD1848P(chip, REGSEL));
226 outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); 225 outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL));
227 if (timeout == 0x80) 226 if (reg == 0x80)
228 snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); 227 snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
229 if ((timeout & AD1848_MCE) == 0) { 228 if ((reg & AD1848_MCE) == 0) {
230 spin_unlock_irqrestore(&chip->reg_lock, flags); 229 spin_unlock_irqrestore(&chip->reg_lock, flags);
231 return; 230 return;
232 } 231 }
233 232
234 /* 233 /*
235 * Wait for (possible -- during init auto-calibration may not be set) 234 * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
236 * calibration process to start. Needs upto 5 sample periods on AD1848 235 * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
237 * which at the slowest possible rate of 5.5125 kHz means 907 us. 236 * the process to _start_, so it is important to wait at least that long
237 * before checking. Otherwise we might think AC has finished when it
238 * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles
239 * for ACI to drop. This gives a wait of at most 70 ms with a more
240 * typical value of 3-9 ms.
238 */ 241 */
239 spin_unlock_irqrestore(&chip->reg_lock, flags); 242 timeout = jiffies + msecs_to_jiffies(250);
240 msleep(1); 243 do {
241 spin_lock_irqsave(&chip->reg_lock, flags);
242
243 snd_printdd("(2) jiffies = %lu\n", jiffies);
244
245 end_time = jiffies + msecs_to_jiffies(250);
246 while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) {
247 spin_unlock_irqrestore(&chip->reg_lock, flags); 244 spin_unlock_irqrestore(&chip->reg_lock, flags);
248 if (time_after(jiffies, end_time)) {
249 snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n");
250 return;
251 }
252 msleep(1); 245 msleep(1);
253 spin_lock_irqsave(&chip->reg_lock, flags); 246 spin_lock_irqsave(&chip->reg_lock, flags);
254 } 247 reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
255 248 AD1848_CALIB_IN_PROGRESS;
256 snd_printdd("(3) jiffies = %lu\n", jiffies); 249 } while (reg && time_before(jiffies, timeout));
257
258 end_time = jiffies + msecs_to_jiffies(100);
259 while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) {
260 spin_unlock_irqrestore(&chip->reg_lock, flags);
261 if (time_after(jiffies, end_time)) {
262 snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
263 return;
264 }
265 msleep(1);
266 spin_lock_irqsave(&chip->reg_lock, flags);
267 }
268 spin_unlock_irqrestore(&chip->reg_lock, flags); 250 spin_unlock_irqrestore(&chip->reg_lock, flags);
251 if (reg)
252 snd_printk(KERN_ERR
253 "mce_down - auto calibration time out (2)\n");
269 254
270 snd_printdd("(4) jiffies = %lu\n", jiffies); 255 snd_printdd("(4) jiffies = %lu\n", jiffies);
271 snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); 256 snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));