/***************** * timer expires * *****************/ void dsp_tone_timeout(struct timer_list *t) { struct dsp *dsp = from_timer(dsp, t, tone.tl); struct dsp_tone *tone = &dsp->tone; struct pattern *pat = (struct pattern *)tone->pattern; int index = tone->index; if (!tone->tone) return; index++; if (!pat->seq[index]) index = 0; tone->index = index; /* set next tone */ if (pat->data[index] == DATA_S) dsp_tone_hw_message(dsp, NULL, 0); else dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index])); /* set timer */ tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000; add_timer(&tone->tl); }
/* * tones are relaized by streaming or by special loop commands if supported * by hardware. when hardware is used, the patterns will be controlled by * timers. */ int dsp_tone(struct dsp *dsp, int tone) { struct pattern *pat; int i; struct dsp_tone *tonet = &dsp->tone; tonet->software = 0; tonet->hardware = 0; /* we turn off the tone */ if (!tone) { if (dsp->features.hfc_loops && timer_pending(&tonet->tl)) del_timer(&tonet->tl); if (dsp->features.hfc_loops) dsp_tone_hw_message(dsp, NULL, 0); tonet->tone = 0; return 0; } pat = NULL; i = 0; while (pattern[i].tone) { if (pattern[i].tone == tone) { pat = &pattern[i]; break; } i++; } if (!pat) { printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone); return -EINVAL; } if (dsp_debug & DEBUG_DSP_TONE) printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n", __func__, tone, 0); tonet->tone = tone; tonet->pattern = pat; tonet->index = 0; tonet->count = 0; if (dsp->features.hfc_loops) { tonet->hardware = 1; /* set first tone */ dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0])); /* set timer */ if (timer_pending(&tonet->tl)) del_timer(&tonet->tl); init_timer(&tonet->tl); tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000; add_timer(&tonet->tl); } else { tonet->software = 1; } return 0; }