162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * OPL4 mixer functions 462306a36Sopenharmony_ci * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "opl4_local.h" 862306a36Sopenharmony_ci#include <sound/control.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistatic int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1362306a36Sopenharmony_ci uinfo->count = 2; 1462306a36Sopenharmony_ci uinfo->value.integer.min = 0; 1562306a36Sopenharmony_ci uinfo->value.integer.max = 7; 1662306a36Sopenharmony_ci return 0; 1762306a36Sopenharmony_ci} 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 2262306a36Sopenharmony_ci unsigned long flags; 2362306a36Sopenharmony_ci u8 reg = kcontrol->private_value; 2462306a36Sopenharmony_ci u8 value; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci spin_lock_irqsave(&opl4->reg_lock, flags); 2762306a36Sopenharmony_ci value = snd_opl4_read(opl4, reg); 2862306a36Sopenharmony_ci spin_unlock_irqrestore(&opl4->reg_lock, flags); 2962306a36Sopenharmony_ci ucontrol->value.integer.value[0] = 7 - (value & 7); 3062306a36Sopenharmony_ci ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); 3162306a36Sopenharmony_ci return 0; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 3762306a36Sopenharmony_ci unsigned long flags; 3862306a36Sopenharmony_ci u8 reg = kcontrol->private_value; 3962306a36Sopenharmony_ci u8 value, old_value; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci value = (7 - (ucontrol->value.integer.value[0] & 7)) | 4262306a36Sopenharmony_ci ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); 4362306a36Sopenharmony_ci spin_lock_irqsave(&opl4->reg_lock, flags); 4462306a36Sopenharmony_ci old_value = snd_opl4_read(opl4, reg); 4562306a36Sopenharmony_ci snd_opl4_write(opl4, reg, value); 4662306a36Sopenharmony_ci spin_unlock_irqrestore(&opl4->reg_lock, flags); 4762306a36Sopenharmony_ci return value != old_value; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic const struct snd_kcontrol_new snd_opl4_controls[] = { 5162306a36Sopenharmony_ci { 5262306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5362306a36Sopenharmony_ci .name = "FM Playback Volume", 5462306a36Sopenharmony_ci .info = snd_opl4_ctl_info, 5562306a36Sopenharmony_ci .get = snd_opl4_ctl_get, 5662306a36Sopenharmony_ci .put = snd_opl4_ctl_put, 5762306a36Sopenharmony_ci .private_value = OPL4_REG_MIX_CONTROL_FM 5862306a36Sopenharmony_ci }, 5962306a36Sopenharmony_ci { 6062306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6162306a36Sopenharmony_ci .name = "Wavetable Playback Volume", 6262306a36Sopenharmony_ci .info = snd_opl4_ctl_info, 6362306a36Sopenharmony_ci .get = snd_opl4_ctl_get, 6462306a36Sopenharmony_ci .put = snd_opl4_ctl_put, 6562306a36Sopenharmony_ci .private_value = OPL4_REG_MIX_CONTROL_PCM 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciint snd_opl4_create_mixer(struct snd_opl4 *opl4) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct snd_card *card = opl4->card; 7262306a36Sopenharmony_ci int i, err; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci strcat(card->mixername, ",OPL4"); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci for (i = 0; i < 2; ++i) { 7762306a36Sopenharmony_ci err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); 7862306a36Sopenharmony_ci if (err < 0) 7962306a36Sopenharmony_ci return err; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci return 0; 8262306a36Sopenharmony_ci} 83