18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * OPL4 mixer functions 48c2ecf20Sopenharmony_ci * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "opl4_local.h" 88c2ecf20Sopenharmony_ci#include <sound/control.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistatic int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 118c2ecf20Sopenharmony_ci{ 128c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 138c2ecf20Sopenharmony_ci uinfo->count = 2; 148c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 158c2ecf20Sopenharmony_ci uinfo->value.integer.max = 7; 168c2ecf20Sopenharmony_ci return 0; 178c2ecf20Sopenharmony_ci} 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 228c2ecf20Sopenharmony_ci unsigned long flags; 238c2ecf20Sopenharmony_ci u8 reg = kcontrol->private_value; 248c2ecf20Sopenharmony_ci u8 value; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci spin_lock_irqsave(&opl4->reg_lock, flags); 278c2ecf20Sopenharmony_ci value = snd_opl4_read(opl4, reg); 288c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&opl4->reg_lock, flags); 298c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = 7 - (value & 7); 308c2ecf20Sopenharmony_ci ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); 318c2ecf20Sopenharmony_ci return 0; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); 378c2ecf20Sopenharmony_ci unsigned long flags; 388c2ecf20Sopenharmony_ci u8 reg = kcontrol->private_value; 398c2ecf20Sopenharmony_ci u8 value, old_value; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci value = (7 - (ucontrol->value.integer.value[0] & 7)) | 428c2ecf20Sopenharmony_ci ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); 438c2ecf20Sopenharmony_ci spin_lock_irqsave(&opl4->reg_lock, flags); 448c2ecf20Sopenharmony_ci old_value = snd_opl4_read(opl4, reg); 458c2ecf20Sopenharmony_ci snd_opl4_write(opl4, reg, value); 468c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&opl4->reg_lock, flags); 478c2ecf20Sopenharmony_ci return value != old_value; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new snd_opl4_controls[] = { 518c2ecf20Sopenharmony_ci { 528c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 538c2ecf20Sopenharmony_ci .name = "FM Playback Volume", 548c2ecf20Sopenharmony_ci .info = snd_opl4_ctl_info, 558c2ecf20Sopenharmony_ci .get = snd_opl4_ctl_get, 568c2ecf20Sopenharmony_ci .put = snd_opl4_ctl_put, 578c2ecf20Sopenharmony_ci .private_value = OPL4_REG_MIX_CONTROL_FM 588c2ecf20Sopenharmony_ci }, 598c2ecf20Sopenharmony_ci { 608c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 618c2ecf20Sopenharmony_ci .name = "Wavetable Playback Volume", 628c2ecf20Sopenharmony_ci .info = snd_opl4_ctl_info, 638c2ecf20Sopenharmony_ci .get = snd_opl4_ctl_get, 648c2ecf20Sopenharmony_ci .put = snd_opl4_ctl_put, 658c2ecf20Sopenharmony_ci .private_value = OPL4_REG_MIX_CONTROL_PCM 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciint snd_opl4_create_mixer(struct snd_opl4 *opl4) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct snd_card *card = opl4->card; 728c2ecf20Sopenharmony_ci int i, err; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci strcat(card->mixername, ",OPL4"); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci for (i = 0; i < 2; ++i) { 778c2ecf20Sopenharmony_ci err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); 788c2ecf20Sopenharmony_ci if (err < 0) 798c2ecf20Sopenharmony_ci return err; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci} 83