static void snd_hda_do_detach(struct hda_beep *beep)
 {
-       input_unregister_device(beep->dev);
+       if (beep->registered)
+               input_unregister_device(beep->dev);
+       else
+               input_free_device(beep->dev);
        beep->dev = NULL;
        turn_off_beep(beep);
 }
 {
        struct input_dev *input_dev;
        struct hda_codec *codec = beep->codec;
-       int err;
 
        input_dev = input_allocate_device();
        if (!input_dev)
        input_dev->dev.parent = &codec->dev;
        input_set_drvdata(input_dev, beep);
 
-       err = input_register_device(input_dev);
-       if (err < 0) {
-               input_free_device(input_dev);
-               codec_err(codec, "hda_beep: unable to register input device\n");
-               return err;
-       }
        beep->dev = input_dev;
        return 0;
 }
 }
 EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
 
+int snd_hda_register_beep_device(struct hda_codec *codec)
+{
+       struct hda_beep *beep = codec->beep;
+       int err;
+
+       if (!beep || !beep->dev)
+               return 0;
+
+       err = input_register_device(beep->dev);
+       if (err < 0) {
+               codec_err(codec, "hda_beep: unable to register input device\n");
+               input_free_device(beep->dev);
+               codec->beep = NULL;
+               kfree(beep);
+               return err;
+       }
+       beep->registered = true;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hda_register_beep_device);
+
 static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
        char phys[32];
        int tone;
        hda_nid_t nid;
+       unsigned int registered:1;
        unsigned int enabled:1;
        unsigned int linear_tone:1;     /* linear tone for IDT/STAC codec */
        unsigned int playing:1;
 int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
 void snd_hda_detach_beep_device(struct hda_codec *codec);
+int snd_hda_register_beep_device(struct hda_codec *codec);
 #else
 static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
 {
 static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
 {
 }
+static inline int snd_hda_register_beep_device(struct hda_codec *codec)
+{
+       return 0;
+}
 #endif
 #endif
 
 static int snd_hda_codec_dev_register(struct snd_device *device)
 {
        struct hda_codec *codec = device->device_data;
+       int err = device_add(&codec->dev);
 
-       return device_add(&codec->dev);
+       if (err < 0)
+               return err;
+       snd_hda_register_beep_device(codec);
+       return 0;
 }
 
 static int snd_hda_codec_dev_disconnect(struct snd_device *device)
 {
        struct hda_codec *codec = device->device_data;
 
+       snd_hda_detach_beep_device(codec);
        device_del(&codec->dev);
        return 0;
 }
                                  bus->pcm_dev_bits);
                }
        }
+       snd_hda_detach_beep_device(codec);
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
        memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
 
 void snd_hda_gen_free(struct hda_codec *codec)
 {
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
-       snd_hda_detach_beep_device(codec);
        snd_hda_gen_spec_free(codec->spec);
        kfree(codec->spec);
        codec->spec = NULL;
 
 
 static void conexant_free(struct hda_codec *codec)
 {
-       struct conexant_spec *spec = codec->spec;
-       snd_hda_detach_beep_device(codec);
-       kfree(spec);
+       kfree(codec->spec);
 }
 
 static const struct snd_kcontrol_new cxt_capture_mixers[] = {