1 /* 2 * Digital Beep Input Interface for HD-audio codec 3 * 4 * Author: Matthew Ranostay <mranostay@embeddedalley.com> 5 * Copyright (c) 2008 Embedded Alley Solutions Inc 6 * 7 * This driver is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This driver is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #include <linux/input.h> 23 #include <linux/slab.h> 24 #include <linux/workqueue.h> 25 #include <linux/export.h> 26 #include <sound/core.h> 27 #include "hda_beep.h" 28 #include "hda_local.h" 29 30 enum { 31 DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */ 32 DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */ 33 DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ 34 }; 35 36 static void snd_hda_generate_beep(struct work_struct *work) 37 { 38 struct hda_beep *beep = 39 container_of(work, struct hda_beep, beep_work); 40 struct hda_codec *codec = beep->codec; 41 int tone; 42 43 if (!beep->enabled) 44 return; 45 46 tone = beep->tone; 47 if (tone && !beep->playing) { 48 snd_hda_power_up(codec); 49 beep->playing = 1; 50 } 51 /* generate tone */ 52 snd_hda_codec_write(codec, beep->nid, 0, 53 AC_VERB_SET_BEEP_CONTROL, tone); 54 if (!tone && beep->playing) { 55 beep->playing = 0; 56 snd_hda_power_down(codec); 57 } 58 } 59 60 /* (non-standard) Linear beep tone calculation for IDT/STAC codecs 61 * 62 * The tone frequency of beep generator on IDT/STAC codecs is 63 * defined from the 8bit tone parameter, in Hz, 64 * freq = 48000 * (257 - tone) / 1024 65 * that is from 12kHz to 93.75Hz in steps of 46.875 Hz 66 */ 67 static int beep_linear_tone(struct hda_beep *beep, int hz) 68 { 69 if (hz <= 0) 70 return 0; 71 hz *= 1000; /* fixed point */ 72 hz = hz - DIGBEEP_HZ_MIN 73 + DIGBEEP_HZ_STEP / 2; /* round to nearest step */ 74 if (hz < 0) 75 hz = 0; /* turn off PC beep*/ 76 else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) 77 hz = 1; /* max frequency */ 78 else { 79 hz /= DIGBEEP_HZ_STEP; 80 hz = 255 - hz; 81 } 82 return hz; 83 } 84 85 /* HD-audio standard beep tone parameter calculation 86 * 87 * The tone frequency in Hz is calculated as 88 * freq = 48000 / (tone * 4) 89 * from 47Hz to 12kHz 90 */ 91 static int beep_standard_tone(struct hda_beep *beep, int hz) 92 { 93 if (hz <= 0) 94 return 0; /* disabled */ 95 hz = 12000 / hz; 96 if (hz > 0xff) 97 return 0xff; 98 if (hz <= 0) 99 return 1; 100 return hz; 101 } 102 103 static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, 104 unsigned int code, int hz) 105 { 106 struct hda_beep *beep = input_get_drvdata(dev); 107 108 switch (code) { 109 case SND_BELL: 110 if (hz) 111 hz = 1000; 112 /* fallthru */ 113 case SND_TONE: 114 if (beep->linear_tone) 115 beep->tone = beep_linear_tone(beep, hz); 116 else 117 beep->tone = beep_standard_tone(beep, hz); 118 break; 119 default: 120 return -1; 121 } 122 123 /* schedule beep event */ 124 schedule_work(&beep->beep_work); 125 return 0; 126 } 127 128 static void turn_off_beep(struct hda_beep *beep) 129 { 130 cancel_work_sync(&beep->beep_work); 131 if (beep->playing) { 132 /* turn off beep */ 133 snd_hda_codec_write(beep->codec, beep->nid, 0, 134 AC_VERB_SET_BEEP_CONTROL, 0); 135 beep->playing = 0; 136 snd_hda_power_down(beep->codec); 137 } 138 } 139 140 static void snd_hda_do_detach(struct hda_beep *beep) 141 { 142 if (beep->registered) 143 input_unregister_device(beep->dev); 144 else 145 input_free_device(beep->dev); 146 beep->dev = NULL; 147 turn_off_beep(beep); 148 } 149 150 static int snd_hda_do_attach(struct hda_beep *beep) 151 { 152 struct input_dev *input_dev; 153 struct hda_codec *codec = beep->codec; 154 155 input_dev = input_allocate_device(); 156 if (!input_dev) 157 return -ENOMEM; 158 159 /* setup digital beep device */ 160 input_dev->name = "HDA Digital PCBeep"; 161 input_dev->phys = beep->phys; 162 input_dev->id.bustype = BUS_PCI; 163 164 input_dev->id.vendor = codec->vendor_id >> 16; 165 input_dev->id.product = codec->vendor_id & 0xffff; 166 input_dev->id.version = 0x01; 167 168 input_dev->evbit[0] = BIT_MASK(EV_SND); 169 input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); 170 input_dev->event = snd_hda_beep_event; 171 input_dev->dev.parent = &codec->dev; 172 input_set_drvdata(input_dev, beep); 173 174 beep->dev = input_dev; 175 return 0; 176 } 177 178 /** 179 * snd_hda_enable_beep_device - Turn on/off beep sound 180 * @codec: the HDA codec 181 * @enable: flag to turn on/off 182 */ 183 int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) 184 { 185 struct hda_beep *beep = codec->beep; 186 if (!beep) 187 return 0; 188 enable = !!enable; 189 if (beep->enabled != enable) { 190 beep->enabled = enable; 191 if (!enable) 192 turn_off_beep(beep); 193 return 1; 194 } 195 return 0; 196 } 197 EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device); 198 199 /** 200 * snd_hda_attach_beep_device - Attach a beep input device 201 * @codec: the HDA codec 202 * @nid: beep NID 203 * 204 * Attach a beep object to the given widget. If beep hint is turned off 205 * explicitly or beep_mode of the codec is turned off, this doesn't nothing. 206 * 207 * The attached beep device has to be registered via 208 * snd_hda_register_beep_device() and released via snd_hda_detach_beep_device() 209 * appropriately. 210 * 211 * Currently, only one beep device is allowed to each codec. 212 */ 213 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) 214 { 215 struct hda_beep *beep; 216 int err; 217 218 if (!snd_hda_get_bool_hint(codec, "beep")) 219 return 0; /* disabled explicitly by hints */ 220 if (codec->beep_mode == HDA_BEEP_MODE_OFF) 221 return 0; /* disabled by module option */ 222 223 beep = kzalloc(sizeof(*beep), GFP_KERNEL); 224 if (beep == NULL) 225 return -ENOMEM; 226 snprintf(beep->phys, sizeof(beep->phys), 227 "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); 228 /* enable linear scale */ 229 snd_hda_codec_write_cache(codec, nid, 0, 230 AC_VERB_SET_DIGI_CONVERT_2, 0x01); 231 232 beep->nid = nid; 233 beep->codec = codec; 234 codec->beep = beep; 235 236 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); 237 mutex_init(&beep->mutex); 238 239 err = snd_hda_do_attach(beep); 240 if (err < 0) { 241 kfree(beep); 242 codec->beep = NULL; 243 return err; 244 } 245 246 return 0; 247 } 248 EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device); 249 250 /** 251 * snd_hda_detach_beep_device - Detach the beep device 252 * @codec: the HDA codec 253 */ 254 void snd_hda_detach_beep_device(struct hda_codec *codec) 255 { 256 struct hda_beep *beep = codec->beep; 257 if (beep) { 258 if (beep->dev) 259 snd_hda_do_detach(beep); 260 codec->beep = NULL; 261 kfree(beep); 262 } 263 } 264 EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); 265 266 /** 267 * snd_hda_register_beep_device - Register the beep device 268 * @codec: the HDA codec 269 */ 270 int snd_hda_register_beep_device(struct hda_codec *codec) 271 { 272 struct hda_beep *beep = codec->beep; 273 int err; 274 275 if (!beep || !beep->dev) 276 return 0; 277 278 err = input_register_device(beep->dev); 279 if (err < 0) { 280 codec_err(codec, "hda_beep: unable to register input device\n"); 281 input_free_device(beep->dev); 282 codec->beep = NULL; 283 kfree(beep); 284 return err; 285 } 286 beep->registered = true; 287 return 0; 288 } 289 EXPORT_SYMBOL_GPL(snd_hda_register_beep_device); 290 291 static bool ctl_has_mute(struct snd_kcontrol *kcontrol) 292 { 293 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 294 return query_amp_caps(codec, get_amp_nid(kcontrol), 295 get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE; 296 } 297 298 /* get/put callbacks for beep mute mixer switches */ 299 300 /** 301 * snd_hda_mixer_amp_switch_get_beep - Get callback for beep controls 302 * @kcontrol: ctl element 303 * @ucontrol: pointer to get/store the data 304 */ 305 int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, 306 struct snd_ctl_elem_value *ucontrol) 307 { 308 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 309 struct hda_beep *beep = codec->beep; 310 if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) { 311 ucontrol->value.integer.value[0] = 312 ucontrol->value.integer.value[1] = beep->enabled; 313 return 0; 314 } 315 return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 316 } 317 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep); 318 319 /** 320 * snd_hda_mixer_amp_switch_put_beep - Put callback for beep controls 321 * @kcontrol: ctl element 322 * @ucontrol: pointer to get/store the data 323 */ 324 int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, 325 struct snd_ctl_elem_value *ucontrol) 326 { 327 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 328 struct hda_beep *beep = codec->beep; 329 if (beep) { 330 u8 chs = get_amp_channels(kcontrol); 331 int enable = 0; 332 long *valp = ucontrol->value.integer.value; 333 if (chs & 1) { 334 enable |= *valp; 335 valp++; 336 } 337 if (chs & 2) 338 enable |= *valp; 339 snd_hda_enable_beep_device(codec, enable); 340 } 341 if (!ctl_has_mute(kcontrol)) 342 return 0; 343 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 344 } 345 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep); 346