.. | .. |
---|
102 | 102 | case SND_BELL: |
---|
103 | 103 | if (hz) |
---|
104 | 104 | hz = 1000; |
---|
105 | | - /* fallthru */ |
---|
| 105 | + fallthrough; |
---|
106 | 106 | case SND_TONE: |
---|
107 | 107 | if (beep->linear_tone) |
---|
108 | 108 | beep->tone = beep_linear_tone(beep, hz); |
---|
.. | .. |
---|
118 | 118 | return 0; |
---|
119 | 119 | } |
---|
120 | 120 | |
---|
| 121 | +static void turn_on_beep(struct hda_beep *beep) |
---|
| 122 | +{ |
---|
| 123 | + if (beep->keep_power_at_enable) |
---|
| 124 | + snd_hda_power_up_pm(beep->codec); |
---|
| 125 | +} |
---|
| 126 | + |
---|
121 | 127 | static void turn_off_beep(struct hda_beep *beep) |
---|
122 | 128 | { |
---|
123 | 129 | cancel_work_sync(&beep->beep_work); |
---|
.. | .. |
---|
125 | 131 | /* turn off beep */ |
---|
126 | 132 | generate_tone(beep, 0); |
---|
127 | 133 | } |
---|
128 | | -} |
---|
129 | | - |
---|
130 | | -static void snd_hda_do_detach(struct hda_beep *beep) |
---|
131 | | -{ |
---|
132 | | - if (beep->registered) |
---|
133 | | - input_unregister_device(beep->dev); |
---|
134 | | - else |
---|
135 | | - input_free_device(beep->dev); |
---|
136 | | - beep->dev = NULL; |
---|
137 | | - turn_off_beep(beep); |
---|
138 | | -} |
---|
139 | | - |
---|
140 | | -static int snd_hda_do_attach(struct hda_beep *beep) |
---|
141 | | -{ |
---|
142 | | - struct input_dev *input_dev; |
---|
143 | | - struct hda_codec *codec = beep->codec; |
---|
144 | | - |
---|
145 | | - input_dev = input_allocate_device(); |
---|
146 | | - if (!input_dev) |
---|
147 | | - return -ENOMEM; |
---|
148 | | - |
---|
149 | | - /* setup digital beep device */ |
---|
150 | | - input_dev->name = "HDA Digital PCBeep"; |
---|
151 | | - input_dev->phys = beep->phys; |
---|
152 | | - input_dev->id.bustype = BUS_PCI; |
---|
153 | | - input_dev->dev.parent = &codec->card->card_dev; |
---|
154 | | - |
---|
155 | | - input_dev->id.vendor = codec->core.vendor_id >> 16; |
---|
156 | | - input_dev->id.product = codec->core.vendor_id & 0xffff; |
---|
157 | | - input_dev->id.version = 0x01; |
---|
158 | | - |
---|
159 | | - input_dev->evbit[0] = BIT_MASK(EV_SND); |
---|
160 | | - input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); |
---|
161 | | - input_dev->event = snd_hda_beep_event; |
---|
162 | | - input_set_drvdata(input_dev, beep); |
---|
163 | | - |
---|
164 | | - beep->dev = input_dev; |
---|
165 | | - return 0; |
---|
| 134 | + if (beep->keep_power_at_enable) |
---|
| 135 | + snd_hda_power_down_pm(beep->codec); |
---|
166 | 136 | } |
---|
167 | 137 | |
---|
168 | 138 | /** |
---|
.. | .. |
---|
178 | 148 | enable = !!enable; |
---|
179 | 149 | if (beep->enabled != enable) { |
---|
180 | 150 | beep->enabled = enable; |
---|
181 | | - if (!enable) |
---|
| 151 | + if (enable) |
---|
| 152 | + turn_on_beep(beep); |
---|
| 153 | + else |
---|
182 | 154 | turn_off_beep(beep); |
---|
183 | 155 | return 1; |
---|
184 | 156 | } |
---|
185 | 157 | return 0; |
---|
186 | 158 | } |
---|
187 | 159 | EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device); |
---|
| 160 | + |
---|
| 161 | +static int beep_dev_register(struct snd_device *device) |
---|
| 162 | +{ |
---|
| 163 | + struct hda_beep *beep = device->device_data; |
---|
| 164 | + int err; |
---|
| 165 | + |
---|
| 166 | + err = input_register_device(beep->dev); |
---|
| 167 | + if (!err) |
---|
| 168 | + beep->registered = true; |
---|
| 169 | + return err; |
---|
| 170 | +} |
---|
| 171 | + |
---|
| 172 | +static int beep_dev_disconnect(struct snd_device *device) |
---|
| 173 | +{ |
---|
| 174 | + struct hda_beep *beep = device->device_data; |
---|
| 175 | + |
---|
| 176 | + if (beep->registered) |
---|
| 177 | + input_unregister_device(beep->dev); |
---|
| 178 | + else |
---|
| 179 | + input_free_device(beep->dev); |
---|
| 180 | + if (beep->enabled) |
---|
| 181 | + turn_off_beep(beep); |
---|
| 182 | + return 0; |
---|
| 183 | +} |
---|
| 184 | + |
---|
| 185 | +static int beep_dev_free(struct snd_device *device) |
---|
| 186 | +{ |
---|
| 187 | + struct hda_beep *beep = device->device_data; |
---|
| 188 | + |
---|
| 189 | + beep->codec->beep = NULL; |
---|
| 190 | + kfree(beep); |
---|
| 191 | + return 0; |
---|
| 192 | +} |
---|
188 | 193 | |
---|
189 | 194 | /** |
---|
190 | 195 | * snd_hda_attach_beep_device - Attach a beep input device |
---|
.. | .. |
---|
194 | 199 | * Attach a beep object to the given widget. If beep hint is turned off |
---|
195 | 200 | * explicitly or beep_mode of the codec is turned off, this doesn't nothing. |
---|
196 | 201 | * |
---|
197 | | - * The attached beep device has to be registered via |
---|
198 | | - * snd_hda_register_beep_device() and released via snd_hda_detach_beep_device() |
---|
199 | | - * appropriately. |
---|
200 | | - * |
---|
201 | 202 | * Currently, only one beep device is allowed to each codec. |
---|
202 | 203 | */ |
---|
203 | 204 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) |
---|
204 | 205 | { |
---|
| 206 | + static const struct snd_device_ops ops = { |
---|
| 207 | + .dev_register = beep_dev_register, |
---|
| 208 | + .dev_disconnect = beep_dev_disconnect, |
---|
| 209 | + .dev_free = beep_dev_free, |
---|
| 210 | + }; |
---|
| 211 | + struct input_dev *input_dev; |
---|
205 | 212 | struct hda_beep *beep; |
---|
206 | 213 | int err; |
---|
207 | 214 | |
---|
.. | .. |
---|
226 | 233 | INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); |
---|
227 | 234 | mutex_init(&beep->mutex); |
---|
228 | 235 | |
---|
229 | | - err = snd_hda_do_attach(beep); |
---|
230 | | - if (err < 0) { |
---|
231 | | - kfree(beep); |
---|
232 | | - codec->beep = NULL; |
---|
233 | | - return err; |
---|
| 236 | + input_dev = input_allocate_device(); |
---|
| 237 | + if (!input_dev) { |
---|
| 238 | + err = -ENOMEM; |
---|
| 239 | + goto err_free; |
---|
234 | 240 | } |
---|
235 | 241 | |
---|
| 242 | + /* setup digital beep device */ |
---|
| 243 | + input_dev->name = "HDA Digital PCBeep"; |
---|
| 244 | + input_dev->phys = beep->phys; |
---|
| 245 | + input_dev->id.bustype = BUS_PCI; |
---|
| 246 | + input_dev->dev.parent = &codec->card->card_dev; |
---|
| 247 | + |
---|
| 248 | + input_dev->id.vendor = codec->core.vendor_id >> 16; |
---|
| 249 | + input_dev->id.product = codec->core.vendor_id & 0xffff; |
---|
| 250 | + input_dev->id.version = 0x01; |
---|
| 251 | + |
---|
| 252 | + input_dev->evbit[0] = BIT_MASK(EV_SND); |
---|
| 253 | + input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); |
---|
| 254 | + input_dev->event = snd_hda_beep_event; |
---|
| 255 | + input_set_drvdata(input_dev, beep); |
---|
| 256 | + |
---|
| 257 | + beep->dev = input_dev; |
---|
| 258 | + |
---|
| 259 | + err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops); |
---|
| 260 | + if (err < 0) |
---|
| 261 | + goto err_input; |
---|
| 262 | + |
---|
236 | 263 | return 0; |
---|
| 264 | + |
---|
| 265 | + err_input: |
---|
| 266 | + input_free_device(beep->dev); |
---|
| 267 | + err_free: |
---|
| 268 | + kfree(beep); |
---|
| 269 | + codec->beep = NULL; |
---|
| 270 | + return err; |
---|
237 | 271 | } |
---|
238 | 272 | EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device); |
---|
239 | 273 | |
---|
.. | .. |
---|
243 | 277 | */ |
---|
244 | 278 | void snd_hda_detach_beep_device(struct hda_codec *codec) |
---|
245 | 279 | { |
---|
246 | | - struct hda_beep *beep = codec->beep; |
---|
247 | | - if (beep) { |
---|
248 | | - if (beep->dev) |
---|
249 | | - snd_hda_do_detach(beep); |
---|
250 | | - codec->beep = NULL; |
---|
251 | | - kfree(beep); |
---|
252 | | - } |
---|
| 280 | + if (!codec->bus->shutdown && codec->beep) |
---|
| 281 | + snd_device_free(codec->card, codec->beep); |
---|
253 | 282 | } |
---|
254 | 283 | EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); |
---|
255 | | - |
---|
256 | | -/** |
---|
257 | | - * snd_hda_register_beep_device - Register the beep device |
---|
258 | | - * @codec: the HDA codec |
---|
259 | | - */ |
---|
260 | | -int snd_hda_register_beep_device(struct hda_codec *codec) |
---|
261 | | -{ |
---|
262 | | - struct hda_beep *beep = codec->beep; |
---|
263 | | - int err; |
---|
264 | | - |
---|
265 | | - if (!beep || !beep->dev) |
---|
266 | | - return 0; |
---|
267 | | - |
---|
268 | | - err = input_register_device(beep->dev); |
---|
269 | | - if (err < 0) { |
---|
270 | | - codec_err(codec, "hda_beep: unable to register input device\n"); |
---|
271 | | - input_free_device(beep->dev); |
---|
272 | | - codec->beep = NULL; |
---|
273 | | - kfree(beep); |
---|
274 | | - return err; |
---|
275 | | - } |
---|
276 | | - beep->registered = true; |
---|
277 | | - return 0; |
---|
278 | | -} |
---|
279 | | -EXPORT_SYMBOL_GPL(snd_hda_register_beep_device); |
---|
280 | 284 | |
---|
281 | 285 | static bool ctl_has_mute(struct snd_kcontrol *kcontrol) |
---|
282 | 286 | { |
---|