diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index aaece36247e7..6e8ee1d6974a 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -109,7 +109,6 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
 	return 0;
 
  error:
-	pm_runtime_put_noidle(&codec->dev);
 	put_device(&codec->dev);
 	return err;
 }
@@ -121,7 +120,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_init);
  */
 void snd_hdac_device_exit(struct hdac_device *codec)
 {
-	/* pm_runtime_put_noidle(&codec->dev); */
+	pm_runtime_put_noidle(&codec->dev);
 	snd_hdac_bus_remove_device(codec->bus, codec);
 	kfree(codec->vendor_name);
 	kfree(codec->chip_name);
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index 130f672e6f37..7b269c3237e3 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -95,6 +95,7 @@ static int hda_codec_driver_probe(struct device *dev)
 		err = snd_card_register(codec->card);
 		if (err < 0)
 			goto error_module;
+		snd_hda_codec_register(codec);
 	}
 
 	return 0;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 36483f7dd3ce..145cae7903b6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -912,6 +912,13 @@ static void codec_release_pcms(struct hda_codec *codec)
 
 void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
 {
+	if (codec->registered) {
+		/* pm_runtime_put() is called in snd_hdac_device_exit() */
+		pm_runtime_get_noresume(hda_codec_dev(codec));
+		pm_runtime_disable(hda_codec_dev(codec));
+		codec->registered = 0;
+	}
+
 	cancel_delayed_work_sync(&codec->jackpoll_work);
 	if (!codec->in_freeing)
 		snd_hda_ctls_clear(codec);
@@ -943,15 +950,23 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
 static unsigned int hda_set_power_state(struct hda_codec *codec,
 				unsigned int power_state);
 
+/* also called from hda_bind.c */
+void snd_hda_codec_register(struct hda_codec *codec)
+{
+	if (codec->registered)
+		return;
+	if (device_is_registered(hda_codec_dev(codec))) {
+		snd_hda_register_beep_device(codec);
+		pm_runtime_enable(hda_codec_dev(codec));
+		/* it was powered up in snd_hda_codec_new(), now all done */
+		snd_hda_power_down(codec);
+		codec->registered = 1;
+	}
+}
+
 static int snd_hda_codec_dev_register(struct snd_device *device)
 {
-	struct hda_codec *codec = device->device_data;
-
-	snd_hda_register_beep_device(codec);
-	if (device_is_registered(hda_codec_dev(codec)))
-		pm_runtime_enable(hda_codec_dev(codec));
-	/* it was powered up in snd_hda_codec_new(), now all done */
-	snd_hda_power_down(codec);
+	snd_hda_codec_register(device->device_data);
 	return 0;
 }
 
@@ -1094,7 +1109,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
 	return 0;
 
  error:
-	pm_runtime_put_noidle(hda_codec_dev(codec));
 	put_device(hda_codec_dev(codec));
 	return err;
 }
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index e7c47a439762..76776164623d 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -314,6 +314,7 @@ struct hda_codec {
 
 	/* misc flags */
 	unsigned int in_freeing:1; /* being released */
+	unsigned int registered:1; /* codec was registered */
 	unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
 					     * status change
 					     * (e.g. Realtek codecs)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index e0db30c66e5f..8a83775e0e27 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -150,6 +150,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 #define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \
 	__snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL)
 int snd_hda_codec_reset(struct hda_codec *codec);
+void snd_hda_codec_register(struct hda_codec *codec);
 void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec);
 
 enum {