unsigned int maximum_usec_per_period;
int err;
- hw->info = SNDRV_PCM_INFO_BATCH |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ hw->info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_JOINT_DUPLEX |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID;
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_NO_PERIOD_WAKEUP;
- /* SNDRV_PCM_INFO_BATCH */
hw->periods_min = 2;
hw->periods_max = UINT_MAX;
s->pcm_period_pointer += frames;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
- queue_work(system_highpri_wq, &s->period_work);
+
+ // The program in user process should periodically check the status of intermediate
+ // buffer associated to PCM substream to process PCM frames in the buffer, instead
+ // of receiving notification of period elapsed by poll wait.
+ if (!pcm->runtime->no_period_wakeup)
+ queue_work(system_highpri_wq, &s->period_work);
}
}
unsigned int event_count = s->ctx_data.rx.event_count;
unsigned int pkt_header_length;
unsigned int packets;
+ bool need_hw_irq;
int i;
if (s->packet_index < 0)
else
pkt_header_length = 0;
+ if (s == d->irq_target) {
+ // At NO_PERIOD_WAKEUP mode, the packets for all IT/IR contexts are processed by
+ // the tasks of user process operating ALSA PCM character device by calling ioctl(2)
+ // with some requests, instead of scheduled hardware IRQ of an IT context.
+ struct snd_pcm_substream *pcm = READ_ONCE(s->pcm);
+ need_hw_irq = !pcm || !pcm->runtime->no_period_wakeup;
+ } else {
+ need_hw_irq = false;
+ }
+
for (i = 0; i < packets; ++i) {
const struct pkt_desc *desc = s->pkt_descs + i;
struct {
event_count += desc->data_blocks;
if (event_count >= events_per_period) {
event_count -= events_per_period;
- sched_irq = true;
+ sched_irq = need_hw_irq;
}
}