1/* 2 * PC-Speaker driver for Linux 3 * 4 * Mixer implementation. 5 * Copyright (C) 2001-2008 Stas Sergeev 6 */ 7 8#include <sound/core.h> 9#include <sound/control.h> 10#include "pcsp.h" 11 12 13static int pcsp_enable_info(struct snd_kcontrol *kcontrol, 14 struct snd_ctl_elem_info *uinfo) 15{ 16 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 17 uinfo->count = 1; 18 uinfo->value.integer.min = 0; 19 uinfo->value.integer.max = 1; 20 return 0; 21} 22 23static int pcsp_enable_get(struct snd_kcontrol *kcontrol, 24 struct snd_ctl_elem_value *ucontrol) 25{ 26 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 27 ucontrol->value.integer.value[0] = chip->enable; 28 return 0; 29} 30 31static int pcsp_enable_put(struct snd_kcontrol *kcontrol, 32 struct snd_ctl_elem_value *ucontrol) 33{ 34 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 35 int changed = 0; 36 int enab = ucontrol->value.integer.value[0]; 37 if (enab != chip->enable) { 38 chip->enable = enab; 39 changed = 1; 40 } 41 return changed; 42} 43 44static int pcsp_treble_info(struct snd_kcontrol *kcontrol, 45 struct snd_ctl_elem_info *uinfo) 46{ 47 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 48 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 49 uinfo->count = 1; 50 uinfo->value.enumerated.items = chip->max_treble + 1; 51 if (uinfo->value.enumerated.item > chip->max_treble) 52 uinfo->value.enumerated.item = chip->max_treble; 53 sprintf(uinfo->value.enumerated.name, "%lu", 54 (unsigned long)PCSP_CALC_RATE(uinfo->value.enumerated.item)); 55 return 0; 56} 57 58static int pcsp_treble_get(struct snd_kcontrol *kcontrol, 59 struct snd_ctl_elem_value *ucontrol) 60{ 61 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 62 ucontrol->value.enumerated.item[0] = chip->treble; 63 return 0; 64} 65 66static int pcsp_treble_put(struct snd_kcontrol *kcontrol, 67 struct snd_ctl_elem_value *ucontrol) 68{ 69 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 70 int changed = 0; 71 int treble = ucontrol->value.enumerated.item[0]; 72 if (treble != chip->treble) { 73 chip->treble = treble; 74#if PCSP_DEBUG 75 printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE()); 76#endif 77 changed = 1; 78 } 79 return changed; 80} 81 82static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol, 83 struct snd_ctl_elem_info *uinfo) 84{ 85 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 86 uinfo->count = 1; 87 uinfo->value.integer.min = 0; 88 uinfo->value.integer.max = 1; 89 return 0; 90} 91 92static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol, 93 struct snd_ctl_elem_value *ucontrol) 94{ 95 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 96 ucontrol->value.integer.value[0] = chip->pcspkr; 97 return 0; 98} 99 100static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, 101 struct snd_ctl_elem_value *ucontrol) 102{ 103 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 104 int changed = 0; 105 int spkr = ucontrol->value.integer.value[0]; 106 if (spkr != chip->pcspkr) { 107 chip->pcspkr = spkr; 108 changed = 1; 109 } 110 return changed; 111} 112 113#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \ 114{ \ 115 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 116 .name = ctl_name, \ 117 .info = pcsp_##ctl_type##_info, \ 118 .get = pcsp_##ctl_type##_get, \ 119 .put = pcsp_##ctl_type##_put, \ 120} 121 122static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = { 123 PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), 124 PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), 125}; 126 127static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = { 128 PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"), 129}; 130 131static int snd_pcsp_ctls_add(struct snd_pcsp *chip, 132 struct snd_kcontrol_new *ctls, int num) 133{ 134 int i, err; 135 struct snd_card *card = chip->card; 136 for (i = 0; i < num; i++) { 137 err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip)); 138 if (err < 0) 139 return err; 140 } 141 return 0; 142} 143 144int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm) 145{ 146 int err; 147 struct snd_card *card = chip->card; 148 149 if (!nopcm) { 150 err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm, 151 ARRAY_SIZE(snd_pcsp_controls_pcm)); 152 if (err < 0) 153 return err; 154 } 155 err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr, 156 ARRAY_SIZE(snd_pcsp_controls_spkr)); 157 if (err < 0) 158 return err; 159 160 strcpy(card->mixername, "PC-Speaker"); 161 162 return 0; 163} 164