1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * OPL4 mixer functions 4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> 5 */ 6 7 #include "opl4_local.h" 8 #include <sound/control.h> 9 10 static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 11 { 12 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 13 uinfo->count = 2; 14 uinfo->value.integer.min = 0; 15 uinfo->value.integer.max = 7; 16 return 0; 17 } 18 19 static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20 { 21 struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 22 unsigned long flags; 23 u8 reg = kcontrol->private_value; 24 u8 value; 25 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); 31 return 0; 32 } 33 34 static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 35 { 36 struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 37 unsigned long flags; 38 u8 reg = kcontrol->private_value; 39 u8 value, old_value; 40 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; 48 } 49 50 static struct snd_kcontrol_new snd_opl4_controls[] = { 51 { 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 58 }, 59 { 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 66 } 67 }; 68 69 int snd_opl4_create_mixer(struct snd_opl4 *opl4) 70 { 71 struct snd_card *card = opl4->card; 72 int i, err; 73 74 strcat(card->mixername, ",OPL4"); 75 76 for (i = 0; i < 2; ++i) { 77 err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); 78 if (err < 0) 79 return err; 80 } 81 return 0; 82 } 83