Blame view
sound/pci/hda/hda_beep.c
6.73 KB
1cd2224cd ALSA: hda: digita... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* * Digital Beep Input Interface for HD-audio codec * * Author: Matthew Ranostay <mranostay@embeddedalley.com> * Copyright (c) 2008 Embedded Alley Solutions Inc * * This driver is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This driver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/input.h> #include <linux/pci.h> |
5a0e3ad6a include cleanup: ... |
24 |
#include <linux/slab.h> |
1cd2224cd ALSA: hda: digita... |
25 |
#include <linux/workqueue.h> |
d81a6d717 sound: Add export... |
26 |
#include <linux/export.h> |
1cd2224cd ALSA: hda: digita... |
27 28 |
#include <sound/core.h> #include "hda_beep.h" |
b7b51141b ALSA: hda - Check... |
29 |
#include "hda_local.h" |
1cd2224cd ALSA: hda: digita... |
30 31 32 33 34 35 36 37 38 39 40 41 |
enum { DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */ DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */ DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ }; static void snd_hda_generate_beep(struct work_struct *work) { struct hda_beep *beep = container_of(work, struct hda_beep, beep_work); struct hda_codec *codec = beep->codec; |
4d4e9bb33 ALSA: hda - Add d... |
42 43 |
if (!beep->enabled) return; |
1cd2224cd ALSA: hda: digita... |
44 |
/* generate tone */ |
411fe85c7 ALSA: hda - Don't... |
45 |
snd_hda_codec_write(codec, beep->nid, 0, |
1cd2224cd ALSA: hda: digita... |
46 47 |
AC_VERB_SET_BEEP_CONTROL, beep->tone); } |
fa7979663 ALSA: hda - Fix d... |
48 49 50 51 52 |
/* (non-standard) Linear beep tone calculation for IDT/STAC codecs * * The tone frequency of beep generator on IDT/STAC codecs is * defined from the 8bit tone parameter, in Hz, * freq = 48000 * (257 - tone) / 1024 |
369693dc9 ALSA: hda - fix b... |
53 |
* that is from 12kHz to 93.75Hz in steps of 46.875 Hz |
fa7979663 ALSA: hda - Fix d... |
54 55 56 |
*/ static int beep_linear_tone(struct hda_beep *beep, int hz) { |
369693dc9 ALSA: hda - fix b... |
57 58 |
if (hz <= 0) return 0; |
fa7979663 ALSA: hda - Fix d... |
59 |
hz *= 1000; /* fixed point */ |
369693dc9 ALSA: hda - fix b... |
60 61 |
hz = hz - DIGBEEP_HZ_MIN + DIGBEEP_HZ_STEP / 2; /* round to nearest step */ |
fa7979663 ALSA: hda - Fix d... |
62 63 64 |
if (hz < 0) hz = 0; /* turn off PC beep*/ else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) |
369693dc9 ALSA: hda - fix b... |
65 |
hz = 1; /* max frequency */ |
fa7979663 ALSA: hda - Fix d... |
66 67 |
else { hz /= DIGBEEP_HZ_STEP; |
369693dc9 ALSA: hda - fix b... |
68 |
hz = 255 - hz; |
fa7979663 ALSA: hda - Fix d... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
} return hz; } /* HD-audio standard beep tone parameter calculation * * The tone frequency in Hz is calculated as * freq = 48000 / (tone * 4) * from 47Hz to 12kHz */ static int beep_standard_tone(struct hda_beep *beep, int hz) { if (hz <= 0) return 0; /* disabled */ hz = 12000 / hz; if (hz > 0xff) return 0xff; if (hz <= 0) return 1; return hz; } |
1cd2224cd ALSA: hda: digita... |
90 91 92 93 94 95 96 97 98 99 |
static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz) { struct hda_beep *beep = input_get_drvdata(dev); switch (code) { case SND_BELL: if (hz) hz = 1000; case SND_TONE: |
fa7979663 ALSA: hda - Fix d... |
100 101 102 103 |
if (beep->linear_tone) beep->tone = beep_linear_tone(beep, hz); else beep->tone = beep_standard_tone(beep, hz); |
1cd2224cd ALSA: hda: digita... |
104 105 106 107 |
break; default: return -1; } |
1cd2224cd ALSA: hda: digita... |
108 109 110 111 112 |
/* schedule beep event */ schedule_work(&beep->beep_work); return 0; } |
123c07aed ALSA: hda_intel: ... |
113 114 115 116 117 118 |
static void snd_hda_do_detach(struct hda_beep *beep) { input_unregister_device(beep->dev); beep->dev = NULL; cancel_work_sync(&beep->beep_work); /* turn off beep for sure */ |
411fe85c7 ALSA: hda - Don't... |
119 |
snd_hda_codec_write(beep->codec, beep->nid, 0, |
123c07aed ALSA: hda_intel: ... |
120 121 122 123 |
AC_VERB_SET_BEEP_CONTROL, 0); } static int snd_hda_do_attach(struct hda_beep *beep) |
1cd2224cd ALSA: hda: digita... |
124 125 |
{ struct input_dev *input_dev; |
123c07aed ALSA: hda_intel: ... |
126 |
struct hda_codec *codec = beep->codec; |
1cd2224cd ALSA: hda: digita... |
127 |
int err; |
1cd2224cd ALSA: hda: digita... |
128 |
input_dev = input_allocate_device(); |
6a12afb56 ALSA: hda - Missi... |
129 |
if (!input_dev) { |
123c07aed ALSA: hda_intel: ... |
130 131 |
printk(KERN_INFO "hda_beep: unable to allocate input device "); |
6a12afb56 ALSA: hda - Missi... |
132 133 |
return -ENOMEM; } |
1cd2224cd ALSA: hda: digita... |
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
/* setup digital beep device */ input_dev->name = "HDA Digital PCBeep"; input_dev->phys = beep->phys; input_dev->id.bustype = BUS_PCI; input_dev->id.vendor = codec->vendor_id >> 16; input_dev->id.product = codec->vendor_id & 0xffff; input_dev->id.version = 0x01; input_dev->evbit[0] = BIT_MASK(EV_SND); input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); input_dev->event = snd_hda_beep_event; input_dev->dev.parent = &codec->bus->pci->dev; input_set_drvdata(input_dev, beep); err = input_register_device(input_dev); if (err < 0) { |
f6154d6d0 ALSA: hda - use i... |
152 |
input_free_device(input_dev); |
123c07aed ALSA: hda_intel: ... |
153 154 |
printk(KERN_INFO "hda_beep: unable to register input device "); |
1cd2224cd ALSA: hda: digita... |
155 156 |
return err; } |
123c07aed ALSA: hda_intel: ... |
157 158 159 160 161 162 163 164 |
beep->dev = input_dev; return 0; } static void snd_hda_do_register(struct work_struct *work) { struct hda_beep *beep = container_of(work, struct hda_beep, register_work); |
123c07aed ALSA: hda_intel: ... |
165 166 |
mutex_lock(&beep->mutex); |
13dab0808 ALSA: hda_intel: ... |
167 168 169 170 171 172 173 174 175 176 177 178 179 |
if (beep->enabled && !beep->dev) snd_hda_do_attach(beep); mutex_unlock(&beep->mutex); } static void snd_hda_do_unregister(struct work_struct *work) { struct hda_beep *beep = container_of(work, struct hda_beep, unregister_work.work); mutex_lock(&beep->mutex); if (!beep->enabled && beep->dev) snd_hda_do_detach(beep); |
123c07aed ALSA: hda_intel: ... |
180 181 182 183 184 185 186 |
mutex_unlock(&beep->mutex); } int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) { struct hda_beep *beep = codec->beep; enable = !!enable; |
13dab0808 ALSA: hda_intel: ... |
187 188 189 190 |
if (beep == NULL) return 0; if (beep->enabled != enable) { beep->enabled = enable; |
2dca0bba7 ALSA: hda - add b... |
191 |
if (!enable) { |
13dab0808 ALSA: hda_intel: ... |
192 |
/* turn off beep */ |
411fe85c7 ALSA: hda - Don't... |
193 |
snd_hda_codec_write(beep->codec, beep->nid, 0, |
13dab0808 ALSA: hda_intel: ... |
194 |
AC_VERB_SET_BEEP_CONTROL, 0); |
2dca0bba7 ALSA: hda - add b... |
195 196 197 198 199 200 201 202 203 |
} if (beep->mode == HDA_BEEP_MODE_SWREG) { if (enable) { cancel_delayed_work(&beep->unregister_work); schedule_work(&beep->register_work); } else { schedule_delayed_work(&beep->unregister_work, HZ); } |
13dab0808 ALSA: hda_intel: ... |
204 |
} |
123c07aed ALSA: hda_intel: ... |
205 206 207 208 209 210 211 212 213 214 215 |
return 1; } return 0; } EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { struct hda_beep *beep; if (!snd_hda_get_bool_hint(codec, "beep")) |
9bb1fe390 ALSA: hda - Fix b... |
216 217 218 |
return 0; /* disabled explicitly by hints */ if (codec->beep_mode == HDA_BEEP_MODE_OFF) return 0; /* disabled by module option */ |
1cd2224cd ALSA: hda: digita... |
219 |
|
123c07aed ALSA: hda_intel: ... |
220 221 222 223 224 |
beep = kzalloc(sizeof(*beep), GFP_KERNEL); if (beep == NULL) return -ENOMEM; snprintf(beep->phys, sizeof(beep->phys), "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); |
1cd2224cd ALSA: hda: digita... |
225 226 227 228 229 |
/* enable linear scale */ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, 0x01); beep->nid = nid; |
1cd2224cd ALSA: hda: digita... |
230 |
beep->codec = codec; |
2dca0bba7 ALSA: hda - add b... |
231 |
beep->mode = codec->beep_mode; |
1cd2224cd ALSA: hda: digita... |
232 |
codec->beep = beep; |
123c07aed ALSA: hda_intel: ... |
233 |
INIT_WORK(&beep->register_work, &snd_hda_do_register); |
13dab0808 ALSA: hda_intel: ... |
234 |
INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister); |
1cd2224cd ALSA: hda: digita... |
235 |
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); |
123c07aed ALSA: hda_intel: ... |
236 |
mutex_init(&beep->mutex); |
2dca0bba7 ALSA: hda - add b... |
237 |
if (beep->mode == HDA_BEEP_MODE_ON) { |
54f7190b2 ALSA: hda - Fix O... |
238 239 240 241 242 243 |
int err = snd_hda_do_attach(beep); if (err < 0) { kfree(beep); codec->beep = NULL; return err; } |
2dca0bba7 ALSA: hda - add b... |
244 |
} |
1cd2224cd ALSA: hda: digita... |
245 246 |
return 0; } |
ff7a32673 ALSA: hda - Don't... |
247 |
EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); |
1cd2224cd ALSA: hda: digita... |
248 249 250 251 252 |
void snd_hda_detach_beep_device(struct hda_codec *codec) { struct hda_beep *beep = codec->beep; if (beep) { |
123c07aed ALSA: hda_intel: ... |
253 |
cancel_work_sync(&beep->register_work); |
5f8166975 ALSA: hda: beep -... |
254 |
cancel_delayed_work(&beep->unregister_work); |
54f7190b2 ALSA: hda - Fix O... |
255 |
if (beep->dev) |
123c07aed ALSA: hda_intel: ... |
256 |
snd_hda_do_detach(beep); |
c44765b8c ALSA: hda - Clear... |
257 |
codec->beep = NULL; |
123c07aed ALSA: hda_intel: ... |
258 |
kfree(beep); |
1cd2224cd ALSA: hda: digita... |
259 260 |
} } |
ff7a32673 ALSA: hda - Don't... |
261 |
EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); |