0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/input.h>
0010 #include <linux/slab.h>
0011 #include <linux/workqueue.h>
0012 #include <linux/export.h>
0013 #include <sound/core.h>
0014 #include "hda_beep.h"
0015 #include "hda_local.h"
0016
0017 enum {
0018 DIGBEEP_HZ_STEP = 46875,
0019 DIGBEEP_HZ_MIN = 93750,
0020 DIGBEEP_HZ_MAX = 12000000,
0021 };
0022
0023
0024 static void generate_tone(struct hda_beep *beep, int tone)
0025 {
0026 struct hda_codec *codec = beep->codec;
0027
0028 if (tone && !beep->playing) {
0029 snd_hda_power_up(codec);
0030 if (beep->power_hook)
0031 beep->power_hook(beep, true);
0032 beep->playing = 1;
0033 }
0034 snd_hda_codec_write(codec, beep->nid, 0,
0035 AC_VERB_SET_BEEP_CONTROL, tone);
0036 if (!tone && beep->playing) {
0037 beep->playing = 0;
0038 if (beep->power_hook)
0039 beep->power_hook(beep, false);
0040 snd_hda_power_down(codec);
0041 }
0042 }
0043
0044 static void snd_hda_generate_beep(struct work_struct *work)
0045 {
0046 struct hda_beep *beep =
0047 container_of(work, struct hda_beep, beep_work);
0048
0049 if (beep->enabled)
0050 generate_tone(beep, beep->tone);
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060 static int beep_linear_tone(struct hda_beep *beep, int hz)
0061 {
0062 if (hz <= 0)
0063 return 0;
0064 hz *= 1000;
0065 hz = hz - DIGBEEP_HZ_MIN
0066 + DIGBEEP_HZ_STEP / 2;
0067 if (hz < 0)
0068 hz = 0;
0069 else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
0070 hz = 1;
0071 else {
0072 hz /= DIGBEEP_HZ_STEP;
0073 hz = 255 - hz;
0074 }
0075 return hz;
0076 }
0077
0078
0079
0080
0081
0082
0083
0084 static int beep_standard_tone(struct hda_beep *beep, int hz)
0085 {
0086 if (hz <= 0)
0087 return 0;
0088 hz = 12000 / hz;
0089 if (hz > 0xff)
0090 return 0xff;
0091 if (hz <= 0)
0092 return 1;
0093 return hz;
0094 }
0095
0096 static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
0097 unsigned int code, int hz)
0098 {
0099 struct hda_beep *beep = input_get_drvdata(dev);
0100
0101 switch (code) {
0102 case SND_BELL:
0103 if (hz)
0104 hz = 1000;
0105 fallthrough;
0106 case SND_TONE:
0107 if (beep->linear_tone)
0108 beep->tone = beep_linear_tone(beep, hz);
0109 else
0110 beep->tone = beep_standard_tone(beep, hz);
0111 break;
0112 default:
0113 return -1;
0114 }
0115
0116
0117 schedule_work(&beep->beep_work);
0118 return 0;
0119 }
0120
0121 static void turn_off_beep(struct hda_beep *beep)
0122 {
0123 cancel_work_sync(&beep->beep_work);
0124 if (beep->playing) {
0125
0126 generate_tone(beep, 0);
0127 }
0128 }
0129
0130
0131
0132
0133
0134
0135 int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
0136 {
0137 struct hda_beep *beep = codec->beep;
0138 if (!beep)
0139 return 0;
0140 enable = !!enable;
0141 if (beep->enabled != enable) {
0142 beep->enabled = enable;
0143 if (!enable)
0144 turn_off_beep(beep);
0145 return 1;
0146 }
0147 return 0;
0148 }
0149 EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
0150
0151 static int beep_dev_register(struct snd_device *device)
0152 {
0153 struct hda_beep *beep = device->device_data;
0154 int err;
0155
0156 err = input_register_device(beep->dev);
0157 if (!err)
0158 beep->registered = true;
0159 return err;
0160 }
0161
0162 static int beep_dev_disconnect(struct snd_device *device)
0163 {
0164 struct hda_beep *beep = device->device_data;
0165
0166 if (beep->registered)
0167 input_unregister_device(beep->dev);
0168 else
0169 input_free_device(beep->dev);
0170 turn_off_beep(beep);
0171 return 0;
0172 }
0173
0174 static int beep_dev_free(struct snd_device *device)
0175 {
0176 struct hda_beep *beep = device->device_data;
0177
0178 beep->codec->beep = NULL;
0179 kfree(beep);
0180 return 0;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
0194 {
0195 static const struct snd_device_ops ops = {
0196 .dev_register = beep_dev_register,
0197 .dev_disconnect = beep_dev_disconnect,
0198 .dev_free = beep_dev_free,
0199 };
0200 struct input_dev *input_dev;
0201 struct hda_beep *beep;
0202 int err;
0203
0204 if (!snd_hda_get_bool_hint(codec, "beep"))
0205 return 0;
0206 if (codec->beep_mode == HDA_BEEP_MODE_OFF)
0207 return 0;
0208
0209 beep = kzalloc(sizeof(*beep), GFP_KERNEL);
0210 if (beep == NULL)
0211 return -ENOMEM;
0212 snprintf(beep->phys, sizeof(beep->phys),
0213 "card%d/codec#%d/beep0", codec->card->number, codec->addr);
0214
0215 snd_hda_codec_write_cache(codec, nid, 0,
0216 AC_VERB_SET_DIGI_CONVERT_2, 0x01);
0217
0218 beep->nid = nid;
0219 beep->codec = codec;
0220 codec->beep = beep;
0221
0222 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
0223 mutex_init(&beep->mutex);
0224
0225 input_dev = input_allocate_device();
0226 if (!input_dev) {
0227 err = -ENOMEM;
0228 goto err_free;
0229 }
0230
0231
0232 input_dev->name = "HDA Digital PCBeep";
0233 input_dev->phys = beep->phys;
0234 input_dev->id.bustype = BUS_PCI;
0235 input_dev->dev.parent = &codec->card->card_dev;
0236
0237 input_dev->id.vendor = codec->core.vendor_id >> 16;
0238 input_dev->id.product = codec->core.vendor_id & 0xffff;
0239 input_dev->id.version = 0x01;
0240
0241 input_dev->evbit[0] = BIT_MASK(EV_SND);
0242 input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
0243 input_dev->event = snd_hda_beep_event;
0244 input_set_drvdata(input_dev, beep);
0245
0246 beep->dev = input_dev;
0247
0248 err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
0249 if (err < 0)
0250 goto err_input;
0251
0252 return 0;
0253
0254 err_input:
0255 input_free_device(beep->dev);
0256 err_free:
0257 kfree(beep);
0258 codec->beep = NULL;
0259 return err;
0260 }
0261 EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
0262
0263
0264
0265
0266
0267 void snd_hda_detach_beep_device(struct hda_codec *codec)
0268 {
0269 if (!codec->bus->shutdown && codec->beep)
0270 snd_device_free(codec->card, codec->beep);
0271 }
0272 EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
0273
0274 static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
0275 {
0276 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0277 return query_amp_caps(codec, get_amp_nid(kcontrol),
0278 get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE;
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288 int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
0289 struct snd_ctl_elem_value *ucontrol)
0290 {
0291 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0292 struct hda_beep *beep = codec->beep;
0293 int chs = get_amp_channels(kcontrol);
0294
0295 if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {
0296 if (chs & 1)
0297 ucontrol->value.integer.value[0] = beep->enabled;
0298 if (chs & 2)
0299 ucontrol->value.integer.value[1] = beep->enabled;
0300 return 0;
0301 }
0302 return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
0303 }
0304 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
0305
0306
0307
0308
0309
0310
0311 int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
0312 struct snd_ctl_elem_value *ucontrol)
0313 {
0314 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0315 struct hda_beep *beep = codec->beep;
0316 if (beep) {
0317 u8 chs = get_amp_channels(kcontrol);
0318 int enable = 0;
0319 long *valp = ucontrol->value.integer.value;
0320 if (chs & 1) {
0321 enable |= *valp;
0322 valp++;
0323 }
0324 if (chs & 2)
0325 enable |= *valp;
0326 snd_hda_enable_beep_device(codec, enable);
0327 }
0328 if (!ctl_has_mute(kcontrol))
0329 return 0;
0330 return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
0331 }
0332 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);