pcsp_mixer.c (4130B)
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}