Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by Lee Revell <rlrevell@joe-job.com>
0004  *                   Clemens Ladisch <clemens@ladisch.de>
0005  *  Routines for control of EMU10K1 chips
0006  *
0007  *  BUGS:
0008  *    --
0009  *
0010  *  TODO:
0011  *    --
0012  */
0013 
0014 #include <linux/time.h>
0015 #include <sound/core.h>
0016 #include <sound/emu10k1.h>
0017 
0018 static int snd_emu10k1_timer_start(struct snd_timer *timer)
0019 {
0020     struct snd_emu10k1 *emu;
0021     unsigned long flags;
0022     unsigned int delay;
0023 
0024     emu = snd_timer_chip(timer);
0025     delay = timer->sticks - 1;
0026     if (delay < 5 ) /* minimum time is 5 ticks */
0027         delay = 5;
0028     spin_lock_irqsave(&emu->reg_lock, flags);
0029     snd_emu10k1_intr_enable(emu, INTE_INTERVALTIMERENB);
0030     outw(delay & TIMER_RATE_MASK, emu->port + TIMER);
0031     spin_unlock_irqrestore(&emu->reg_lock, flags);
0032     return 0;
0033 }
0034 
0035 static int snd_emu10k1_timer_stop(struct snd_timer *timer)
0036 {
0037     struct snd_emu10k1 *emu;
0038     unsigned long flags;
0039 
0040     emu = snd_timer_chip(timer);
0041     spin_lock_irqsave(&emu->reg_lock, flags);
0042     snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB);
0043     spin_unlock_irqrestore(&emu->reg_lock, flags);
0044     return 0;
0045 }
0046 
0047 static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer,
0048                            unsigned long *num, unsigned long *den)
0049 {
0050     *num = 1;
0051     *den = 48000;
0052     return 0;
0053 }
0054 
0055 static const struct snd_timer_hardware snd_emu10k1_timer_hw = {
0056     .flags = SNDRV_TIMER_HW_AUTO,
0057     .resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */
0058     .ticks = 1024,
0059     .start = snd_emu10k1_timer_start,
0060     .stop = snd_emu10k1_timer_stop,
0061     .precise_resolution = snd_emu10k1_timer_precise_resolution,
0062 };
0063 
0064 int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
0065 {
0066     struct snd_timer *timer = NULL;
0067     struct snd_timer_id tid;
0068     int err;
0069 
0070     tid.dev_class = SNDRV_TIMER_CLASS_CARD;
0071     tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
0072     tid.card = emu->card->number;
0073     tid.device = device;
0074     tid.subdevice = 0;
0075     err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer);
0076     if (err >= 0) {
0077         strcpy(timer->name, "EMU10K1 timer");
0078         timer->private_data = emu;
0079         timer->hw = snd_emu10k1_timer_hw;
0080     }
0081     emu->timer = timer;
0082     return err;
0083 }