linux/sound/pci/emu10k1/timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (c) by Lee Revell <rlrevell@joe-job.com>
   4 *                   Clemens Ladisch <clemens@ladisch.de>
   5 *  Routines for control of EMU10K1 chips
   6 *
   7 *  BUGS:
   8 *    --
   9 *
  10 *  TODO:
  11 *    --
  12 */
  13
  14#include <linux/time.h>
  15#include <sound/core.h>
  16#include <sound/emu10k1.h>
  17
  18static int snd_emu10k1_timer_start(struct snd_timer *timer)
  19{
  20        struct snd_emu10k1 *emu;
  21        unsigned long flags;
  22        unsigned int delay;
  23
  24        emu = snd_timer_chip(timer);
  25        delay = timer->sticks - 1;
  26        if (delay < 5 ) /* minimum time is 5 ticks */
  27                delay = 5;
  28        spin_lock_irqsave(&emu->reg_lock, flags);
  29        snd_emu10k1_intr_enable(emu, INTE_INTERVALTIMERENB);
  30        outw(delay & TIMER_RATE_MASK, emu->port + TIMER);
  31        spin_unlock_irqrestore(&emu->reg_lock, flags);
  32        return 0;
  33}
  34
  35static int snd_emu10k1_timer_stop(struct snd_timer *timer)
  36{
  37        struct snd_emu10k1 *emu;
  38        unsigned long flags;
  39
  40        emu = snd_timer_chip(timer);
  41        spin_lock_irqsave(&emu->reg_lock, flags);
  42        snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB);
  43        spin_unlock_irqrestore(&emu->reg_lock, flags);
  44        return 0;
  45}
  46
  47static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer,
  48                                               unsigned long *num, unsigned long *den)
  49{
  50        *num = 1;
  51        *den = 48000;
  52        return 0;
  53}
  54
  55static const struct snd_timer_hardware snd_emu10k1_timer_hw = {
  56        .flags = SNDRV_TIMER_HW_AUTO,
  57        .resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */
  58        .ticks = 1024,
  59        .start = snd_emu10k1_timer_start,
  60        .stop = snd_emu10k1_timer_stop,
  61        .precise_resolution = snd_emu10k1_timer_precise_resolution,
  62};
  63
  64int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
  65{
  66        struct snd_timer *timer = NULL;
  67        struct snd_timer_id tid;
  68        int err;
  69
  70        tid.dev_class = SNDRV_TIMER_CLASS_CARD;
  71        tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
  72        tid.card = emu->card->number;
  73        tid.device = device;
  74        tid.subdevice = 0;
  75        err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer);
  76        if (err >= 0) {
  77                strcpy(timer->name, "EMU10K1 timer");
  78                timer->private_data = emu;
  79                timer->hw = snd_emu10k1_timer_hw;
  80        }
  81        emu->timer = timer;
  82        return err;
  83}
  84