165 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * PC-Speaker driver for Linux4 *5 * Mixer implementation.6 * Copyright (C) 2001-2008 Stas Sergeev7 */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_DEBUG76 dev_dbg(chip->card->dev, "PCSP: rate set to %li\n", PCSP_RATE());77#endif78 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