/* write the port and returns the next expire time in ns; * called at the trigger-start and in hrtimer callback */ static unsigned long pcsp_timer_update(struct hrtimer *handle) { unsigned char timer_cnt, val; u64 ns; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); unsigned long flags; if (chip->thalf) { outb(chip->val61, 0x61); chip->thalf = 0; if (!atomic_read(&chip->timer_active)) return 0; return chip->ns_rem; } if (!atomic_read(&chip->timer_active)) return 0; substream = chip->playback_substream; if (!substream) return 0; runtime = substream->runtime; /* assume it is mono! */ val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; if (chip->is_signed) val ^= 0x80; timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); outb(chip->val61 ^ 1, 0x61); } else { outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } spin_unlock_irqrestore(&i8253_lock, flags); } chip->ns_rem = PCSP_PERIOD_NS(); ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); chip->ns_rem -= ns; return ns; }
static u64 pcsp_timer_update(struct snd_pcsp *chip) { unsigned char timer_cnt, val; u64 ns; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; unsigned long flags; if (chip->thalf) { outb(chip->val61, 0x61); chip->thalf = 0; return chip->ns_rem; } substream = chip->playback_substream; if (!substream) return 0; runtime = substream->runtime; val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; if (chip->is_signed) val ^= 0x80; timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { raw_spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); outb(chip->val61 ^ 1, 0x61); } else { outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } raw_spin_unlock_irqrestore(&i8253_lock, flags); } chip->ns_rem = PCSP_PERIOD_NS(); ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); chip->ns_rem -= ns; return ns; }