Loading sound/pci/hda/hda_codec.c +50 −4 Original line number Diff line number Diff line Loading @@ -1445,9 +1445,52 @@ void snd_hda_ctls_clear(struct hda_codec *codec) snd_array_free(&codec->mixers); } void snd_hda_codec_reset(struct hda_codec *codec) /* pseudo device locking * toggle card->shutdown to allow/disallow the device access (as a hack) */ static int hda_lock_devices(struct snd_card *card) { int i; spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); return -EINVAL; } card->shutdown = 1; spin_unlock(&card->files_lock); return 0; } static void hda_unlock_devices(struct snd_card *card) { spin_lock(&card->files_lock); card->shutdown = 0; spin_unlock(&card->files_lock); } int snd_hda_codec_reset(struct hda_codec *codec) { struct snd_card *card = codec->bus->card; int i, pcm; if (hda_lock_devices(card) < 0) return -EBUSY; /* check whether the codec isn't used by any mixer or PCM streams */ if (!list_empty(&card->ctl_files)) { hda_unlock_devices(card); return -EBUSY; } for (pcm = 0; pcm < codec->num_pcms; pcm++) { struct hda_pcm *cpcm = &codec->pcm_info[pcm]; if (!cpcm->pcm) continue; if (cpcm->pcm->streams[0].substream_opened || cpcm->pcm->streams[1].substream_opened) { hda_unlock_devices(card); return -EBUSY; } } /* OK, let it free */ #ifdef CONFIG_SND_HDA_POWER_SAVE cancel_delayed_work(&codec->power_work); Loading @@ -1457,8 +1500,7 @@ void snd_hda_codec_reset(struct hda_codec *codec) /* relase PCMs */ for (i = 0; i < codec->num_pcms; i++) { if (codec->pcm_info[i].pcm) { snd_device_free(codec->bus->card, codec->pcm_info[i].pcm); snd_device_free(card, codec->pcm_info[i].pcm); clear_bit(codec->pcm_info[i].device, codec->bus->pcm_dev_bits); } Loading @@ -1479,6 +1521,10 @@ void snd_hda_codec_reset(struct hda_codec *codec) codec->preset = NULL; module_put(codec->owner); codec->owner = NULL; /* allow device access again */ hda_unlock_devices(card); return 0; } #endif /* CONFIG_SND_HDA_RECONFIG */ Loading sound/pci/hda/hda_hwdep.c +13 −2 Original line number Diff line number Diff line Loading @@ -155,7 +155,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) static int clear_codec(struct hda_codec *codec) { snd_hda_codec_reset(codec); int err; err = snd_hda_codec_reset(codec); if (err < 0) { snd_printk(KERN_ERR "The codec is being used, can't free.\n"); return err; } clear_hwdep_elements(codec); return 0; } Loading @@ -165,7 +171,12 @@ static int reconfig_codec(struct hda_codec *codec) int err; snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); snd_hda_codec_reset(codec); err = snd_hda_codec_reset(codec); if (err < 0) { snd_printk(KERN_ERR "The codec is being used, can't reconfigure.\n"); return err; } err = snd_hda_codec_configure(codec); if (err < 0) return err; Loading sound/pci/hda/hda_local.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); int snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char **slaves); void snd_hda_codec_reset(struct hda_codec *codec); int snd_hda_codec_reset(struct hda_codec *codec); int snd_hda_codec_configure(struct hda_codec *codec); /* amp value bits */ Loading Loading
sound/pci/hda/hda_codec.c +50 −4 Original line number Diff line number Diff line Loading @@ -1445,9 +1445,52 @@ void snd_hda_ctls_clear(struct hda_codec *codec) snd_array_free(&codec->mixers); } void snd_hda_codec_reset(struct hda_codec *codec) /* pseudo device locking * toggle card->shutdown to allow/disallow the device access (as a hack) */ static int hda_lock_devices(struct snd_card *card) { int i; spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); return -EINVAL; } card->shutdown = 1; spin_unlock(&card->files_lock); return 0; } static void hda_unlock_devices(struct snd_card *card) { spin_lock(&card->files_lock); card->shutdown = 0; spin_unlock(&card->files_lock); } int snd_hda_codec_reset(struct hda_codec *codec) { struct snd_card *card = codec->bus->card; int i, pcm; if (hda_lock_devices(card) < 0) return -EBUSY; /* check whether the codec isn't used by any mixer or PCM streams */ if (!list_empty(&card->ctl_files)) { hda_unlock_devices(card); return -EBUSY; } for (pcm = 0; pcm < codec->num_pcms; pcm++) { struct hda_pcm *cpcm = &codec->pcm_info[pcm]; if (!cpcm->pcm) continue; if (cpcm->pcm->streams[0].substream_opened || cpcm->pcm->streams[1].substream_opened) { hda_unlock_devices(card); return -EBUSY; } } /* OK, let it free */ #ifdef CONFIG_SND_HDA_POWER_SAVE cancel_delayed_work(&codec->power_work); Loading @@ -1457,8 +1500,7 @@ void snd_hda_codec_reset(struct hda_codec *codec) /* relase PCMs */ for (i = 0; i < codec->num_pcms; i++) { if (codec->pcm_info[i].pcm) { snd_device_free(codec->bus->card, codec->pcm_info[i].pcm); snd_device_free(card, codec->pcm_info[i].pcm); clear_bit(codec->pcm_info[i].device, codec->bus->pcm_dev_bits); } Loading @@ -1479,6 +1521,10 @@ void snd_hda_codec_reset(struct hda_codec *codec) codec->preset = NULL; module_put(codec->owner); codec->owner = NULL; /* allow device access again */ hda_unlock_devices(card); return 0; } #endif /* CONFIG_SND_HDA_RECONFIG */ Loading
sound/pci/hda/hda_hwdep.c +13 −2 Original line number Diff line number Diff line Loading @@ -155,7 +155,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) static int clear_codec(struct hda_codec *codec) { snd_hda_codec_reset(codec); int err; err = snd_hda_codec_reset(codec); if (err < 0) { snd_printk(KERN_ERR "The codec is being used, can't free.\n"); return err; } clear_hwdep_elements(codec); return 0; } Loading @@ -165,7 +171,12 @@ static int reconfig_codec(struct hda_codec *codec) int err; snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); snd_hda_codec_reset(codec); err = snd_hda_codec_reset(codec); if (err < 0) { snd_printk(KERN_ERR "The codec is being used, can't reconfigure.\n"); return err; } err = snd_hda_codec_configure(codec); if (err < 0) return err; Loading
sound/pci/hda/hda_local.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, const char *name); int snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char **slaves); void snd_hda_codec_reset(struct hda_codec *codec); int snd_hda_codec_reset(struct hda_codec *codec); int snd_hda_codec_configure(struct hda_codec *codec); /* amp value bits */ Loading