aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c54
-rw-r--r--sound/pci/hda/hda_hwdep.c15
-rw-r--r--sound/pci/hda/hda_local.h2
3 files changed, 64 insertions, 7 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a13480fa8e74..5dceee8a113b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1445,9 +1445,52 @@ void snd_hda_ctls_clear(struct hda_codec *codec)
1445 snd_array_free(&codec->mixers); 1445 snd_array_free(&codec->mixers);
1446} 1446}
1447 1447
1448void snd_hda_codec_reset(struct hda_codec *codec) 1448/* pseudo device locking
1449 * toggle card->shutdown to allow/disallow the device access (as a hack)
1450 */
1451static int hda_lock_devices(struct snd_card *card)
1449{ 1452{
1450 int i; 1453 spin_lock(&card->files_lock);
1454 if (card->shutdown) {
1455 spin_unlock(&card->files_lock);
1456 return -EINVAL;
1457 }
1458 card->shutdown = 1;
1459 spin_unlock(&card->files_lock);
1460 return 0;
1461}
1462
1463static void hda_unlock_devices(struct snd_card *card)
1464{
1465 spin_lock(&card->files_lock);
1466 card->shutdown = 0;
1467 spin_unlock(&card->files_lock);
1468}
1469
1470int snd_hda_codec_reset(struct hda_codec *codec)
1471{
1472 struct snd_card *card = codec->bus->card;
1473 int i, pcm;
1474
1475 if (hda_lock_devices(card) < 0)
1476 return -EBUSY;
1477 /* check whether the codec isn't used by any mixer or PCM streams */
1478 if (!list_empty(&card->ctl_files)) {
1479 hda_unlock_devices(card);
1480 return -EBUSY;
1481 }
1482 for (pcm = 0; pcm < codec->num_pcms; pcm++) {
1483 struct hda_pcm *cpcm = &codec->pcm_info[pcm];
1484 if (!cpcm->pcm)
1485 continue;
1486 if (cpcm->pcm->streams[0].substream_opened ||
1487 cpcm->pcm->streams[1].substream_opened) {
1488 hda_unlock_devices(card);
1489 return -EBUSY;
1490 }
1491 }
1492
1493 /* OK, let it free */
1451 1494
1452#ifdef CONFIG_SND_HDA_POWER_SAVE 1495#ifdef CONFIG_SND_HDA_POWER_SAVE
1453 cancel_delayed_work(&codec->power_work); 1496 cancel_delayed_work(&codec->power_work);
@@ -1457,8 +1500,7 @@ void snd_hda_codec_reset(struct hda_codec *codec)
1457 /* relase PCMs */ 1500 /* relase PCMs */
1458 for (i = 0; i < codec->num_pcms; i++) { 1501 for (i = 0; i < codec->num_pcms; i++) {
1459 if (codec->pcm_info[i].pcm) { 1502 if (codec->pcm_info[i].pcm) {
1460 snd_device_free(codec->bus->card, 1503 snd_device_free(card, codec->pcm_info[i].pcm);
1461 codec->pcm_info[i].pcm);
1462 clear_bit(codec->pcm_info[i].device, 1504 clear_bit(codec->pcm_info[i].device,
1463 codec->bus->pcm_dev_bits); 1505 codec->bus->pcm_dev_bits);
1464 } 1506 }
@@ -1479,6 +1521,10 @@ void snd_hda_codec_reset(struct hda_codec *codec)
1479 codec->preset = NULL; 1521 codec->preset = NULL;
1480 module_put(codec->owner); 1522 module_put(codec->owner);
1481 codec->owner = NULL; 1523 codec->owner = NULL;
1524
1525 /* allow device access again */
1526 hda_unlock_devices(card);
1527 return 0;
1482} 1528}
1483#endif /* CONFIG_SND_HDA_RECONFIG */ 1529#endif /* CONFIG_SND_HDA_RECONFIG */
1484 1530
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index c660383ef381..4af484b8240c 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -155,7 +155,13 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
155 155
156static int clear_codec(struct hda_codec *codec) 156static int clear_codec(struct hda_codec *codec)
157{ 157{
158 snd_hda_codec_reset(codec); 158 int err;
159
160 err = snd_hda_codec_reset(codec);
161 if (err < 0) {
162 snd_printk(KERN_ERR "The codec is being used, can't free.\n");
163 return err;
164 }
159 clear_hwdep_elements(codec); 165 clear_hwdep_elements(codec);
160 return 0; 166 return 0;
161} 167}
@@ -165,7 +171,12 @@ static int reconfig_codec(struct hda_codec *codec)
165 int err; 171 int err;
166 172
167 snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); 173 snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
168 snd_hda_codec_reset(codec); 174 err = snd_hda_codec_reset(codec);
175 if (err < 0) {
176 snd_printk(KERN_ERR
177 "The codec is being used, can't reconfigure.\n");
178 return err;
179 }
169 err = snd_hda_codec_configure(codec); 180 err = snd_hda_codec_configure(codec);
170 if (err < 0) 181 if (err < 0)
171 return err; 182 return err;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 84e2cf644fd7..4bd82a37a4c8 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -98,7 +98,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
98 const char *name); 98 const char *name);
99int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 99int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
100 unsigned int *tlv, const char **slaves); 100 unsigned int *tlv, const char **slaves);
101void snd_hda_codec_reset(struct hda_codec *codec); 101int snd_hda_codec_reset(struct hda_codec *codec);
102int snd_hda_codec_configure(struct hda_codec *codec); 102int snd_hda_codec_configure(struct hda_codec *codec);
103 103
104/* amp value bits */ 104/* amp value bits */