]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Takashi Iwai <tiwai@suse.de> |
2 | Subject: ALSA: hda - Add digital beep support | |
3 | Patch-mainline: 2.6.28-rc1 | |
4 | References: bnc#398459, bnc#398455 | |
5 | ||
6 | Add the support of digital beep for devices without analog beep. | |
7 | ||
8 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
9 | ||
10 | --- | |
11 | diff -ruN a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c | |
12 | --- a/sound/pci/hda/hda_beep.c | |
13 | +++ b/sound/pci/hda/hda_beep.c | |
14 | @@ -0,0 +1,134 @@ | |
15 | +/* | |
16 | + * Digital Beep Input Interface for HD-audio codec | |
17 | + * | |
18 | + * Author: Matthew Ranostay <mranostay@embeddedalley.com> | |
19 | + * Copyright (c) 2008 Embedded Alley Solutions Inc | |
20 | + * | |
21 | + * This driver is free software; you can redistribute it and/or modify | |
22 | + * it under the terms of the GNU General Public License as published by | |
23 | + * the Free Software Foundation; either version 2 of the License, or | |
24 | + * (at your option) any later version. | |
25 | + * | |
26 | + * This driver is distributed in the hope that it will be useful, | |
27 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
28 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
29 | + * GNU General Public License for more details. | |
30 | + * | |
31 | + * You should have received a copy of the GNU General Public License | |
32 | + * along with this program; if not, write to the Free Software | |
33 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
34 | + */ | |
35 | + | |
36 | +#include <linux/input.h> | |
37 | +#include <linux/pci.h> | |
38 | +#include <linux/workqueue.h> | |
39 | +#include <sound/core.h> | |
40 | +#include "hda_beep.h" | |
41 | + | |
42 | +enum { | |
43 | + DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */ | |
44 | + DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */ | |
45 | + DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ | |
46 | +}; | |
47 | + | |
48 | +static void snd_hda_generate_beep(struct work_struct *work) | |
49 | +{ | |
50 | + struct hda_beep *beep = | |
51 | + container_of(work, struct hda_beep, beep_work); | |
52 | + struct hda_codec *codec = beep->codec; | |
53 | + | |
54 | + /* generate tone */ | |
55 | + snd_hda_codec_write_cache(codec, beep->nid, 0, | |
56 | + AC_VERB_SET_BEEP_CONTROL, beep->tone); | |
57 | +} | |
58 | + | |
59 | +static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, | |
60 | + unsigned int code, int hz) | |
61 | +{ | |
62 | + struct hda_beep *beep = input_get_drvdata(dev); | |
63 | + | |
64 | + switch (code) { | |
65 | + case SND_BELL: | |
66 | + if (hz) | |
67 | + hz = 1000; | |
68 | + case SND_TONE: | |
69 | + hz *= 1000; /* fixed point */ | |
70 | + hz = hz - DIGBEEP_HZ_MIN; | |
71 | + if (hz < 0) | |
72 | + hz = 0; /* turn off PC beep*/ | |
73 | + else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) | |
74 | + hz = 0xff; | |
75 | + else { | |
76 | + hz /= DIGBEEP_HZ_STEP; | |
77 | + hz++; | |
78 | + } | |
79 | + break; | |
80 | + default: | |
81 | + return -1; | |
82 | + } | |
83 | + beep->tone = hz; | |
84 | + | |
85 | + /* schedule beep event */ | |
86 | + schedule_work(&beep->beep_work); | |
87 | + return 0; | |
88 | +} | |
89 | + | |
90 | +int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) | |
91 | +{ | |
92 | + struct input_dev *input_dev; | |
93 | + struct hda_beep *beep; | |
94 | + int err; | |
95 | + | |
96 | + beep = kzalloc(sizeof(*beep), GFP_KERNEL); | |
97 | + if (beep == NULL) | |
98 | + return -ENOMEM; | |
99 | + snprintf(beep->phys, sizeof(beep->phys), | |
100 | + "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); | |
101 | + input_dev = input_allocate_device(); | |
102 | + | |
103 | + /* setup digital beep device */ | |
104 | + input_dev->name = "HDA Digital PCBeep"; | |
105 | + input_dev->phys = beep->phys; | |
106 | + input_dev->id.bustype = BUS_PCI; | |
107 | + | |
108 | + input_dev->id.vendor = codec->vendor_id >> 16; | |
109 | + input_dev->id.product = codec->vendor_id & 0xffff; | |
110 | + input_dev->id.version = 0x01; | |
111 | + | |
112 | + input_dev->evbit[0] = BIT_MASK(EV_SND); | |
113 | + input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); | |
114 | + input_dev->event = snd_hda_beep_event; | |
115 | + input_dev->dev.parent = &codec->bus->pci->dev; | |
116 | + input_set_drvdata(input_dev, beep); | |
117 | + | |
118 | + err = input_register_device(input_dev); | |
119 | + if (err < 0) { | |
120 | + input_free_device(input_dev); | |
121 | + kfree(beep); | |
122 | + return err; | |
123 | + } | |
124 | + | |
125 | + /* enable linear scale */ | |
126 | + snd_hda_codec_write(codec, nid, 0, | |
127 | + AC_VERB_SET_DIGI_CONVERT_2, 0x01); | |
128 | + | |
129 | + beep->nid = nid; | |
130 | + beep->dev = input_dev; | |
131 | + beep->codec = codec; | |
132 | + codec->beep = beep; | |
133 | + | |
134 | + INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); | |
135 | + return 0; | |
136 | +} | |
137 | + | |
138 | +void snd_hda_detach_beep_device(struct hda_codec *codec) | |
139 | +{ | |
140 | + struct hda_beep *beep = codec->beep; | |
141 | + if (beep) { | |
142 | + cancel_work_sync(&beep->beep_work); | |
143 | + flush_scheduled_work(); | |
144 | + | |
145 | + input_unregister_device(beep->dev); | |
146 | + kfree(beep); | |
147 | + } | |
148 | +} | |
149 | diff -ruN a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h | |
150 | --- a/sound/pci/hda/hda_beep.h | |
151 | +++ b/sound/pci/hda/hda_beep.h | |
152 | @@ -0,0 +1,44 @@ | |
153 | +/* | |
154 | + * Digital Beep Input Interface for HD-audio codec | |
155 | + * | |
156 | + * Author: Matthew Ranostay <mranostay@embeddedalley.com> | |
157 | + * Copyright (c) 2008 Embedded Alley Solutions Inc | |
158 | + * | |
159 | + * This driver is free software; you can redistribute it and/or modify | |
160 | + * it under the terms of the GNU General Public License as published by | |
161 | + * the Free Software Foundation; either version 2 of the License, or | |
162 | + * (at your option) any later version. | |
163 | + * | |
164 | + * This driver is distributed in the hope that it will be useful, | |
165 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
166 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
167 | + * GNU General Public License for more details. | |
168 | + * | |
169 | + * You should have received a copy of the GNU General Public License | |
170 | + * along with this program; if not, write to the Free Software | |
171 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
172 | + */ | |
173 | + | |
174 | +#ifndef __SOUND_HDA_BEEP_H | |
175 | +#define __SOUND_HDA_BEEP_H | |
176 | + | |
177 | +#include "hda_codec.h" | |
178 | + | |
179 | +/* beep information */ | |
180 | +struct hda_beep { | |
181 | + struct input_dev *dev; | |
182 | + struct hda_codec *codec; | |
183 | + char phys[32]; | |
184 | + int tone; | |
185 | + int nid; | |
186 | + struct work_struct beep_work; /* scheduled task for beep event */ | |
187 | +}; | |
188 | + | |
189 | +#ifdef CONFIG_SND_HDA_INPUT_BEEP | |
190 | +int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); | |
191 | +void snd_hda_detach_beep_device(struct hda_codec *codec); | |
192 | +#else | |
193 | +#define snd_hda_attach_beep_device(...) | |
194 | +#define snd_hda_detach_beep_device(...) | |
195 | +#endif | |
196 | +#endif | |
197 | diff -ruN a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile | |
198 | --- a/sound/pci/hda/Makefile | |
199 | +++ b/sound/pci/hda/Makefile | |
200 | @@ -5,6 +5,7 @@ | |
201 | snd-hda-intel-y += hda_codec.o | |
202 | snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o | |
203 | snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | |
204 | +snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | |
205 | snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | |
206 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o | |
207 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o | |
208 | diff -ruN a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h | |
209 | --- a/sound/pci/hda/hda_codec.h | |
210 | +++ b/sound/pci/hda/hda_codec.h | |
211 | @@ -449,6 +449,7 @@ | |
212 | */ | |
213 | ||
214 | struct hda_bus; | |
215 | +struct hda_beep; | |
216 | struct hda_codec; | |
217 | struct hda_pcm; | |
218 | struct hda_pcm_stream; | |
219 | @@ -634,6 +635,9 @@ | |
220 | /* codec specific info */ | |
221 | void *spec; | |
222 | ||
223 | + /* beep device */ | |
224 | + struct hda_beep *beep; | |
225 | + | |
226 | /* widget capabilities cache */ | |
227 | unsigned int num_nodes; | |
228 | hda_nid_t start_nid; | |
229 | diff -ruN a/sound/pci/Kconfig b/sound/pci/Kconfig | |
230 | --- a/sound/pci/Kconfig | |
231 | +++ b/sound/pci/Kconfig | |
232 | @@ -517,6 +517,14 @@ | |
233 | This interface can be used for out-of-band communication | |
234 | with codecs for debugging purposes. | |
235 | ||
236 | +config SND_HDA_INPUT_BEEP | |
237 | + bool "Support digital beep via input layer" | |
238 | + depends on SND_HDA_INTEL | |
239 | + depends on INPUT=y || INPUT=SND_HDA_INTEL | |
240 | + help | |
241 | + Say Y here to build a digital beep interface for HD-audio | |
242 | + driver. This interface is used to generate digital beeps. | |
243 | + | |
244 | config SND_HDA_CODEC_REALTEK | |
245 | bool "Build Realtek HD-audio codec support" | |
246 | depends on SND_HDA_INTEL |