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