linux/sound/drivers/opl4/opl4_mixer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * OPL4 mixer functions
   4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
   5 */
   6
   7#include "opl4_local.h"
   8#include <sound/control.h>
   9
  10static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  11{
  12        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  13        uinfo->count = 2;
  14        uinfo->value.integer.min = 0;
  15        uinfo->value.integer.max = 7;
  16        return 0;
  17}
  18
  19static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  20{
  21        struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
  22        unsigned long flags;
  23        u8 reg = kcontrol->private_value;
  24        u8 value;
  25
  26        spin_lock_irqsave(&opl4->reg_lock, flags);
  27        value = snd_opl4_read(opl4, reg);
  28        spin_unlock_irqrestore(&opl4->reg_lock, flags);
  29        ucontrol->value.integer.value[0] = 7 - (value & 7);
  30        ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
  31        return 0;
  32}
  33
  34static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  35{
  36        struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
  37        unsigned long flags;
  38        u8 reg = kcontrol->private_value;
  39        u8 value, old_value;
  40
  41        value = (7 - (ucontrol->value.integer.value[0] & 7)) |
  42                ((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
  43        spin_lock_irqsave(&opl4->reg_lock, flags);
  44        old_value = snd_opl4_read(opl4, reg);
  45        snd_opl4_write(opl4, reg, value);
  46        spin_unlock_irqrestore(&opl4->reg_lock, flags);
  47        return value != old_value;
  48}
  49
  50static const struct snd_kcontrol_new snd_opl4_controls[] = {
  51        {
  52                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  53                .name = "FM Playback Volume",
  54                .info = snd_opl4_ctl_info,
  55                .get = snd_opl4_ctl_get,
  56                .put = snd_opl4_ctl_put,
  57                .private_value = OPL4_REG_MIX_CONTROL_FM
  58        },
  59        {
  60                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  61                .name = "Wavetable Playback Volume",
  62                .info = snd_opl4_ctl_info,
  63                .get = snd_opl4_ctl_get,
  64                .put = snd_opl4_ctl_put,
  65                .private_value = OPL4_REG_MIX_CONTROL_PCM
  66        }
  67};
  68
  69int snd_opl4_create_mixer(struct snd_opl4 *opl4)
  70{
  71        struct snd_card *card = opl4->card;
  72        int i, err;
  73
  74        strcat(card->mixername, ",OPL4");
  75
  76        for (i = 0; i < 2; ++i) {
  77                err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
  78                if (err < 0)
  79                        return err;
  80        }
  81        return 0;
  82}
  83