Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/drivers/pcsp/pcsp_mixer.c
26437 views
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
14
static 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
24
static 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
32
static 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
45
static 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
59
static 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
67
static 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
dev_dbg(chip->card->dev, "PCSP: rate set to %li\n", PCSP_RATE());
77
#endif
78
changed = 1;
79
}
80
return changed;
81
}
82
83
static 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
93
static 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
101
static 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
123
static 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
128
static const struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
129
PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
130
};
131
132
static 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
145
int 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
strscpy(card->mixername, "PC-Speaker");
162
163
return 0;
164
}
165
166