xref: /linux/sound/drivers/opl4/opl4_mixer.c (revision 8dd06ef34b6e2f41b29fbf5fc1663780f2524285)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * OPL4 mixer functions
41da177e4SLinus Torvalds  * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds #include "opl4_local.h"
81da177e4SLinus Torvalds #include <sound/control.h>
91da177e4SLinus Torvalds 
snd_opl4_ctl_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)10a42dd420STakashi Iwai static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
111da177e4SLinus Torvalds {
121da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
131da177e4SLinus Torvalds 	uinfo->count = 2;
141da177e4SLinus Torvalds 	uinfo->value.integer.min = 0;
151da177e4SLinus Torvalds 	uinfo->value.integer.max = 7;
161da177e4SLinus Torvalds 	return 0;
171da177e4SLinus Torvalds }
181da177e4SLinus Torvalds 
snd_opl4_ctl_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)19a42dd420STakashi Iwai static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
201da177e4SLinus Torvalds {
21a42dd420STakashi Iwai 	struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
221da177e4SLinus Torvalds 	unsigned long flags;
231da177e4SLinus Torvalds 	u8 reg = kcontrol->private_value;
241da177e4SLinus Torvalds 	u8 value;
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds 	spin_lock_irqsave(&opl4->reg_lock, flags);
271da177e4SLinus Torvalds 	value = snd_opl4_read(opl4, reg);
281da177e4SLinus Torvalds 	spin_unlock_irqrestore(&opl4->reg_lock, flags);
291da177e4SLinus Torvalds 	ucontrol->value.integer.value[0] = 7 - (value & 7);
301da177e4SLinus Torvalds 	ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
311da177e4SLinus Torvalds 	return 0;
321da177e4SLinus Torvalds }
331da177e4SLinus Torvalds 
snd_opl4_ctl_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)34a42dd420STakashi Iwai static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
351da177e4SLinus Torvalds {
36a42dd420STakashi Iwai 	struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
371da177e4SLinus Torvalds 	unsigned long flags;
381da177e4SLinus Torvalds 	u8 reg = kcontrol->private_value;
391da177e4SLinus Torvalds 	u8 value, old_value;
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 	value = (7 - (ucontrol->value.integer.value[0] & 7)) |
421da177e4SLinus Torvalds 		((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
431da177e4SLinus Torvalds 	spin_lock_irqsave(&opl4->reg_lock, flags);
441da177e4SLinus Torvalds 	old_value = snd_opl4_read(opl4, reg);
451da177e4SLinus Torvalds 	snd_opl4_write(opl4, reg, value);
461da177e4SLinus Torvalds 	spin_unlock_irqrestore(&opl4->reg_lock, flags);
471da177e4SLinus Torvalds 	return value != old_value;
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds 
50*2eccd408STakashi Iwai static const struct snd_kcontrol_new snd_opl4_controls[] = {
511da177e4SLinus Torvalds 	{
521da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
531da177e4SLinus Torvalds 		.name = "FM Playback Volume",
541da177e4SLinus Torvalds 		.info = snd_opl4_ctl_info,
551da177e4SLinus Torvalds 		.get = snd_opl4_ctl_get,
561da177e4SLinus Torvalds 		.put = snd_opl4_ctl_put,
571da177e4SLinus Torvalds 		.private_value = OPL4_REG_MIX_CONTROL_FM
581da177e4SLinus Torvalds 	},
591da177e4SLinus Torvalds 	{
601da177e4SLinus Torvalds 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
611da177e4SLinus Torvalds 		.name = "Wavetable Playback Volume",
621da177e4SLinus Torvalds 		.info = snd_opl4_ctl_info,
631da177e4SLinus Torvalds 		.get = snd_opl4_ctl_get,
641da177e4SLinus Torvalds 		.put = snd_opl4_ctl_put,
651da177e4SLinus Torvalds 		.private_value = OPL4_REG_MIX_CONTROL_PCM
661da177e4SLinus Torvalds 	}
671da177e4SLinus Torvalds };
681da177e4SLinus Torvalds 
snd_opl4_create_mixer(struct snd_opl4 * opl4)69a42dd420STakashi Iwai int snd_opl4_create_mixer(struct snd_opl4 *opl4)
701da177e4SLinus Torvalds {
71a42dd420STakashi Iwai 	struct snd_card *card = opl4->card;
721da177e4SLinus Torvalds 	int i, err;
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds 	strcat(card->mixername, ",OPL4");
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 	for (i = 0; i < 2; ++i) {
771da177e4SLinus Torvalds 		err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
781da177e4SLinus Torvalds 		if (err < 0)
791da177e4SLinus Torvalds 			return err;
801da177e4SLinus Torvalds 	}
811da177e4SLinus Torvalds 	return 0;
821da177e4SLinus Torvalds }
83