1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
7 #include "opl4_local.h"
8 #include <sound/control.h>
10 static int snd_opl4_ctl_info(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_info
*uinfo
)
12 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
14 uinfo
->value
.integer
.min
= 0;
15 uinfo
->value
.integer
.max
= 7;
19 static int snd_opl4_ctl_get(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
21 struct snd_opl4
*opl4
= snd_kcontrol_chip(kcontrol
);
23 u8 reg
= kcontrol
->private_value
;
26 spin_lock_irqsave(&opl4
->reg_lock
, flags
);
27 value
= snd_opl4_read(opl4
, reg
);
28 spin_unlock_irqrestore(&opl4
->reg_lock
, flags
);
29 ucontrol
->value
.integer
.value
[0] = 7 - (value
& 7);
30 ucontrol
->value
.integer
.value
[1] = 7 - ((value
>> 3) & 7);
34 static int snd_opl4_ctl_put(struct snd_kcontrol
*kcontrol
, struct snd_ctl_elem_value
*ucontrol
)
36 struct snd_opl4
*opl4
= snd_kcontrol_chip(kcontrol
);
38 u8 reg
= kcontrol
->private_value
;
41 value
= (7 - (ucontrol
->value
.integer
.value
[0] & 7)) |
42 ((7 - (ucontrol
->value
.integer
.value
[1] & 7)) << 3);
43 spin_lock_irqsave(&opl4
->reg_lock
, flags
);
44 old_value
= snd_opl4_read(opl4
, reg
);
45 snd_opl4_write(opl4
, reg
, value
);
46 spin_unlock_irqrestore(&opl4
->reg_lock
, flags
);
47 return value
!= old_value
;
50 static const struct snd_kcontrol_new snd_opl4_controls
[] = {
52 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
53 .name
= "FM Playback Volume",
54 .info
= snd_opl4_ctl_info
,
55 .get
= snd_opl4_ctl_get
,
56 .put
= snd_opl4_ctl_put
,
57 .private_value
= OPL4_REG_MIX_CONTROL_FM
60 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
61 .name
= "Wavetable Playback Volume",
62 .info
= snd_opl4_ctl_info
,
63 .get
= snd_opl4_ctl_get
,
64 .put
= snd_opl4_ctl_put
,
65 .private_value
= OPL4_REG_MIX_CONTROL_PCM
69 int snd_opl4_create_mixer(struct snd_opl4
*opl4
)
71 struct snd_card
*card
= opl4
->card
;
74 strcat(card
->mixername
, ",OPL4");
76 for (i
= 0; i
< 2; ++i
) {
77 err
= snd_ctl_add(card
, snd_ctl_new1(&snd_opl4_controls
[i
], opl4
));