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 13 static 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 23 static 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 31 static 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 44 static 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, "%d", PCSP_RATE()); 54 return 0; 55 } 56 57 static int pcsp_treble_get(struct snd_kcontrol *kcontrol, 58 struct snd_ctl_elem_value *ucontrol) 59 { 60 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 61 ucontrol->value.enumerated.item[0] = chip->treble; 62 return 0; 63 } 64 65 static int pcsp_treble_put(struct snd_kcontrol *kcontrol, 66 struct snd_ctl_elem_value *ucontrol) 67 { 68 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 69 int changed = 0; 70 int treble = ucontrol->value.enumerated.item[0]; 71 if (treble != chip->treble) { 72 chip->treble = treble; 73 #if PCSP_DEBUG 74 printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE()); 75 #endif 76 changed = 1; 77 } 78 return changed; 79 } 80 81 static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol, 82 struct snd_ctl_elem_info *uinfo) 83 { 84 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 85 uinfo->count = 1; 86 uinfo->value.integer.min = 0; 87 uinfo->value.integer.max = 1; 88 return 0; 89 } 90 91 static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol, 92 struct snd_ctl_elem_value *ucontrol) 93 { 94 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 95 ucontrol->value.integer.value[0] = chip->pcspkr; 96 return 0; 97 } 98 99 static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, 100 struct snd_ctl_elem_value *ucontrol) 101 { 102 struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); 103 int changed = 0; 104 int spkr = ucontrol->value.integer.value[0]; 105 if (spkr != chip->pcspkr) { 106 chip->pcspkr = spkr; 107 changed = 1; 108 } 109 return changed; 110 } 111 112 #define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \ 113 { \ 114 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 115 .name = ctl_name, \ 116 .info = pcsp_##ctl_type##_info, \ 117 .get = pcsp_##ctl_type##_get, \ 118 .put = pcsp_##ctl_type##_put, \ 119 } 120 121 static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = { 122 PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), 123 PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), 124 PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"), 125 }; 126 127 int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip) 128 { 129 struct snd_card *card = chip->card; 130 int i, err; 131 132 for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) { 133 err = snd_ctl_add(card, 134 snd_ctl_new1(snd_pcsp_controls + i, 135 chip)); 136 if (err < 0) 137 return err; 138 } 139 140 strcpy(card->mixername, "PC-Speaker"); 141 142 return 0; 143 } 144