Loading sound/pci/ctxfi/cthardware.h +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ struct hw { int (*set_timer_irq)(struct hw *hw, int enable); int (*set_timer_tick)(struct hw *hw, unsigned int tick); unsigned int (*get_wc)(struct hw *hw); void (*irq_callback)(void *data, unsigned int bit); void *irq_callback_data; Loading sound/pci/ctxfi/cthw20k1.c +6 −0 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,11 @@ static int set_timer_tick(struct hw *hw, unsigned int ticks) return 0; } static unsigned int get_wc(struct hw *hw) { return hw_read_20kx(hw, WC); } /* Card hardware initialization block */ struct dac_conf { unsigned int msr; /* master sample rate in rsrs */ Loading Loading @@ -2235,6 +2240,7 @@ static struct hw ct20k1_preset __devinitdata = { .set_timer_irq = set_timer_irq, .set_timer_tick = set_timer_tick, .get_wc = get_wc, }; int __devinit create_20k1_hw_obj(struct hw **rhw) Loading sound/pci/ctxfi/cttimer.c +48 −28 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct ct_timer { struct ct_timer_ops *ops; struct list_head instance_head; struct list_head running_head; unsigned int wc; /* current wallclock */ unsigned int irq_handling:1; /* in IRQ handling */ unsigned int reprogram:1; /* need to reprogram the internval */ unsigned int running:1; /* global timer running */ Loading Loading @@ -136,6 +137,7 @@ static struct ct_timer_ops ct_systimer_ops = { */ #define CT_TIMER_FREQ 48000 #define MIN_TICKS 1 #define MAX_TICKS ((1 << 13) - 1) static void ct_xfitimer_irq_rearm(struct ct_timer *atimer, int ticks) Loading @@ -159,6 +161,12 @@ static void ct_xfitimer_irq_stop(struct ct_timer *atimer) } } static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) { struct hw *hw = atimer->atc->hw; return hw->get_wc(hw); } /* * reprogram the timer interval; * checks the running instance list and determines the next timer interval. Loading @@ -170,37 +178,46 @@ static void ct_xfitimer_irq_stop(struct ct_timer *atimer) static int ct_xfitimer_reprogram(struct ct_timer *atimer) { struct ct_timer_instance *ti; int min_intr = -1; unsigned int min_intr = (unsigned int)-1; int updates = 0; unsigned int wc, diff; if (list_empty(&atimer->running_head)) { ct_xfitimer_irq_stop(atimer); atimer->reprogram = 0; /* clear flag */ return 0; } wc = ct_xfitimer_get_wc(atimer); diff = wc - atimer->wc; atimer->wc = wc; list_for_each_entry(ti, &atimer->running_head, running_list) { struct snd_pcm_runtime *runtime; unsigned int pos, diff; int intr; runtime = ti->substream->runtime; if (ti->frag_count > diff) ti->frag_count -= diff; else { unsigned int pos; unsigned int period_size, rate; period_size = ti->substream->runtime->period_size; rate = ti->substream->runtime->rate; pos = ti->substream->ops->pointer(ti->substream); if (pos < ti->position) diff = runtime->buffer_size - ti->position + pos; else diff = pos - ti->position; ti->position = pos; while (diff >= ti->frag_count) { ti->frag_count += runtime->period_size; if (pos / period_size != ti->position / period_size) { ti->need_update = 1; ti->position = pos; updates++; } ti->frag_count -= diff; intr = div_u64((u64)ti->frag_count * CT_TIMER_FREQ, runtime->rate); if (min_intr < 0 || intr < min_intr) min_intr = intr; pos %= period_size; pos = period_size - pos; ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + rate - 1, rate); } if (ti->frag_count < min_intr) min_intr = ti->frag_count; } if (min_intr > 0) if (min_intr < MIN_TICKS) min_intr = MIN_TICKS; ct_xfitimer_irq_rearm(atimer, min_intr); else ct_xfitimer_irq_stop(atimer); atimer->reprogram = 0; /* clear flag */ return updates; } Loading Loading @@ -253,13 +270,14 @@ static void ct_xfitimer_update(struct ct_timer *atimer) unsigned long flags; int update; spin_lock_irqsave(&atimer->lock, flags); if (atimer->irq_handling) { /* reached from IRQ handler; let it handle later */ atimer->reprogram = 1; spin_unlock_irqrestore(&atimer->lock, flags); return; } spin_lock_irqsave(&atimer->lock, flags); ct_xfitimer_irq_stop(atimer); update = ct_xfitimer_reprogram(atimer); spin_unlock_irqrestore(&atimer->lock, flags); Loading @@ -273,6 +291,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti) unsigned long flags; spin_lock_irqsave(&atimer->lock, flags); if (list_empty(&ti->running_list)) atimer->wc = ct_xfitimer_get_wc(atimer); list_add(&ti->running_list, &atimer->running_head); spin_unlock_irqrestore(&atimer->lock, flags); ct_xfitimer_update(atimer); Loading Loading @@ -396,12 +416,12 @@ struct ct_timer *ct_timer_new(struct ct_atc *atc) atimer->atc = atc; hw = atc->hw; if (!USE_SYSTEM_TIMER && hw->set_timer_irq) { printk(KERN_INFO "ctxfi: Use xfi-native timer\n"); snd_printd(KERN_INFO "ctxfi: Use xfi-native timer\n"); atimer->ops = &ct_xfitimer_ops; hw->irq_callback_data = atimer; hw->irq_callback = ct_timer_interrupt; } else { printk(KERN_INFO "ctxfi: Use system timer\n"); snd_printd(KERN_INFO "ctxfi: Use system timer\n"); atimer->ops = &ct_systimer_ops; } return atimer; Loading Loading
sound/pci/ctxfi/cthardware.h +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ struct hw { int (*set_timer_irq)(struct hw *hw, int enable); int (*set_timer_tick)(struct hw *hw, unsigned int tick); unsigned int (*get_wc)(struct hw *hw); void (*irq_callback)(void *data, unsigned int bit); void *irq_callback_data; Loading
sound/pci/ctxfi/cthw20k1.c +6 −0 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,11 @@ static int set_timer_tick(struct hw *hw, unsigned int ticks) return 0; } static unsigned int get_wc(struct hw *hw) { return hw_read_20kx(hw, WC); } /* Card hardware initialization block */ struct dac_conf { unsigned int msr; /* master sample rate in rsrs */ Loading Loading @@ -2235,6 +2240,7 @@ static struct hw ct20k1_preset __devinitdata = { .set_timer_irq = set_timer_irq, .set_timer_tick = set_timer_tick, .get_wc = get_wc, }; int __devinit create_20k1_hw_obj(struct hw **rhw) Loading
sound/pci/ctxfi/cttimer.c +48 −28 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct ct_timer { struct ct_timer_ops *ops; struct list_head instance_head; struct list_head running_head; unsigned int wc; /* current wallclock */ unsigned int irq_handling:1; /* in IRQ handling */ unsigned int reprogram:1; /* need to reprogram the internval */ unsigned int running:1; /* global timer running */ Loading Loading @@ -136,6 +137,7 @@ static struct ct_timer_ops ct_systimer_ops = { */ #define CT_TIMER_FREQ 48000 #define MIN_TICKS 1 #define MAX_TICKS ((1 << 13) - 1) static void ct_xfitimer_irq_rearm(struct ct_timer *atimer, int ticks) Loading @@ -159,6 +161,12 @@ static void ct_xfitimer_irq_stop(struct ct_timer *atimer) } } static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) { struct hw *hw = atimer->atc->hw; return hw->get_wc(hw); } /* * reprogram the timer interval; * checks the running instance list and determines the next timer interval. Loading @@ -170,37 +178,46 @@ static void ct_xfitimer_irq_stop(struct ct_timer *atimer) static int ct_xfitimer_reprogram(struct ct_timer *atimer) { struct ct_timer_instance *ti; int min_intr = -1; unsigned int min_intr = (unsigned int)-1; int updates = 0; unsigned int wc, diff; if (list_empty(&atimer->running_head)) { ct_xfitimer_irq_stop(atimer); atimer->reprogram = 0; /* clear flag */ return 0; } wc = ct_xfitimer_get_wc(atimer); diff = wc - atimer->wc; atimer->wc = wc; list_for_each_entry(ti, &atimer->running_head, running_list) { struct snd_pcm_runtime *runtime; unsigned int pos, diff; int intr; runtime = ti->substream->runtime; if (ti->frag_count > diff) ti->frag_count -= diff; else { unsigned int pos; unsigned int period_size, rate; period_size = ti->substream->runtime->period_size; rate = ti->substream->runtime->rate; pos = ti->substream->ops->pointer(ti->substream); if (pos < ti->position) diff = runtime->buffer_size - ti->position + pos; else diff = pos - ti->position; ti->position = pos; while (diff >= ti->frag_count) { ti->frag_count += runtime->period_size; if (pos / period_size != ti->position / period_size) { ti->need_update = 1; ti->position = pos; updates++; } ti->frag_count -= diff; intr = div_u64((u64)ti->frag_count * CT_TIMER_FREQ, runtime->rate); if (min_intr < 0 || intr < min_intr) min_intr = intr; pos %= period_size; pos = period_size - pos; ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + rate - 1, rate); } if (ti->frag_count < min_intr) min_intr = ti->frag_count; } if (min_intr > 0) if (min_intr < MIN_TICKS) min_intr = MIN_TICKS; ct_xfitimer_irq_rearm(atimer, min_intr); else ct_xfitimer_irq_stop(atimer); atimer->reprogram = 0; /* clear flag */ return updates; } Loading Loading @@ -253,13 +270,14 @@ static void ct_xfitimer_update(struct ct_timer *atimer) unsigned long flags; int update; spin_lock_irqsave(&atimer->lock, flags); if (atimer->irq_handling) { /* reached from IRQ handler; let it handle later */ atimer->reprogram = 1; spin_unlock_irqrestore(&atimer->lock, flags); return; } spin_lock_irqsave(&atimer->lock, flags); ct_xfitimer_irq_stop(atimer); update = ct_xfitimer_reprogram(atimer); spin_unlock_irqrestore(&atimer->lock, flags); Loading @@ -273,6 +291,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti) unsigned long flags; spin_lock_irqsave(&atimer->lock, flags); if (list_empty(&ti->running_list)) atimer->wc = ct_xfitimer_get_wc(atimer); list_add(&ti->running_list, &atimer->running_head); spin_unlock_irqrestore(&atimer->lock, flags); ct_xfitimer_update(atimer); Loading Loading @@ -396,12 +416,12 @@ struct ct_timer *ct_timer_new(struct ct_atc *atc) atimer->atc = atc; hw = atc->hw; if (!USE_SYSTEM_TIMER && hw->set_timer_irq) { printk(KERN_INFO "ctxfi: Use xfi-native timer\n"); snd_printd(KERN_INFO "ctxfi: Use xfi-native timer\n"); atimer->ops = &ct_xfitimer_ops; hw->irq_callback_data = atimer; hw->irq_callback = ct_timer_interrupt; } else { printk(KERN_INFO "ctxfi: Use system timer\n"); snd_printd(KERN_INFO "ctxfi: Use system timer\n"); atimer->ops = &ct_systimer_ops; } return atimer; Loading