linux/sound/drivers/pcsp/pcsp_mixer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * PC-Speaker driver for Linux
   4 *
   5 * Mixer implementation.
   6 * Copyright (C) 2001-2008  Stas Sergeev
   7 */
   8
   9#include <sound/core.h>
  10#include <sound/control.h>
  11#include "pcsp.h"
  12
  13
  14static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
  15                            struct snd_ctl_elem_info *uinfo)
  16{
  17        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  18        uinfo->count = 1;
  19        uinfo->value.integer.min = 0;
  20        uinfo->value.integer.max = 1;
  21        return 0;
  22}
  23
  24static int pcsp_enable_get(struct snd_kcontrol *kcontrol,
  25                           struct snd_ctl_elem_value *ucontrol)
  26{
  27        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  28        ucontrol->value.integer.value[0] = chip->enable;
  29        return 0;
  30}
  31
  32static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
  33                           struct snd_ctl_elem_value *ucontrol)
  34{
  35        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  36        int changed = 0;
  37        int enab = ucontrol->value.integer.value[0];
  38        if (enab != chip->enable) {
  39                chip->enable = enab;
  40                changed = 1;
  41        }
  42        return changed;
  43}
  44
  45static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
  46                            struct snd_ctl_elem_info *uinfo)
  47{
  48        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  49        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  50        uinfo->count = 1;
  51        uinfo->value.enumerated.items = chip->max_treble + 1;
  52        if (uinfo->value.enumerated.item > chip->max_treble)
  53                uinfo->value.enumerated.item = chip->max_treble;
  54        sprintf(uinfo->value.enumerated.name, "%lu",
  55                (unsigned long)PCSP_CALC_RATE(uinfo->value.enumerated.item));
  56        return 0;
  57}
  58
  59static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
  60                           struct snd_ctl_elem_value *ucontrol)
  61{
  62        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  63        ucontrol->value.enumerated.item[0] = chip->treble;
  64        return 0;
  65}
  66
  67static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
  68                           struct snd_ctl_elem_value *ucontrol)
  69{
  70        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  71        int changed = 0;
  72        int treble = ucontrol->value.enumerated.item[0];
  73        if (treble != chip->treble) {
  74                chip->treble = treble;
  75#if PCSP_DEBUG
  76                printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE());
  77#endif
  78                changed = 1;
  79        }
  80        return changed;
  81}
  82
  83static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
  84                            struct snd_ctl_elem_info *uinfo)
  85{
  86        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  87        uinfo->count = 1;
  88        uinfo->value.integer.min = 0;
  89        uinfo->value.integer.max = 1;
  90        return 0;
  91}
  92
  93static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
  94                           struct snd_ctl_elem_value *ucontrol)
  95{
  96        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
  97        ucontrol->value.integer.value[0] = chip->pcspkr;
  98        return 0;
  99}
 100
 101static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
 102                           struct snd_ctl_elem_value *ucontrol)
 103{
 104        struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
 105        int changed = 0;
 106        int spkr = ucontrol->value.integer.value[0];
 107        if (spkr != chip->pcspkr) {
 108                chip->pcspkr = spkr;
 109                changed = 1;
 110        }
 111        return changed;
 112}
 113
 114#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
 115{ \
 116        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER, \
 117        .name =         ctl_name, \
 118        .info =         pcsp_##ctl_type##_info, \
 119        .get =          pcsp_##ctl_type##_get, \
 120        .put =          pcsp_##ctl_type##_put, \
 121}
 122
 123static const struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
 124        PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
 125        PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
 126};
 127
 128static const struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
 129        PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
 130};
 131
 132static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
 133                             const struct snd_kcontrol_new *ctls, int num)
 134{
 135        int i, err;
 136        struct snd_card *card = chip->card;
 137        for (i = 0; i < num; i++) {
 138                err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip));
 139                if (err < 0)
 140                        return err;
 141        }
 142        return 0;
 143}
 144
 145int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm)
 146{
 147        int err;
 148        struct snd_card *card = chip->card;
 149
 150        if (!nopcm) {
 151                err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm,
 152                        ARRAY_SIZE(snd_pcsp_controls_pcm));
 153                if (err < 0)
 154                        return err;
 155        }
 156        err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr,
 157                ARRAY_SIZE(snd_pcsp_controls_spkr));
 158        if (err < 0)
 159                return err;
 160
 161        strcpy(card->mixername, "PC-Speaker");
 162
 163        return 0;
 164}
 165