Skip to content

Commit

Permalink
Merge tag 'hda-switcheroo' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/tiwai/sound

Pull VGA-switcheroo audio client support for HD-audio from Takashi Iwai.

This depended on the recent drm pull.

* tag 'hda-switcheroo' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - unlock on error in azx_interrupt()
  ALSA: hda - Support VGA-switcheroo
  ALSA: hda - Export snd_hda_lock_devices()
  ALSA: hda - Check the dead HDMI audio controller by vga-switcheroo
  • Loading branch information
Linus Torvalds committed May 25, 2012
2 parents 4b7eba4 + 6091106 commit 58823de
Show file tree
Hide file tree
Showing 3 changed files with 316 additions and 67 deletions.
66 changes: 39 additions & 27 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,24 +2239,50 @@ void snd_hda_ctls_clear(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 snd_hda_lock_devices(struct hda_bus *bus)
{
struct snd_card *card = bus->card;
struct hda_codec *codec;

spin_lock(&card->files_lock);
if (card->shutdown) {
spin_unlock(&card->files_lock);
return -EINVAL;
}
if (card->shutdown)
goto err_unlock;
card->shutdown = 1;
if (!list_empty(&card->ctl_files))
goto err_clear;

list_for_each_entry(codec, &bus->codec_list, list) {
int pcm;
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)
goto err_clear;
}
}
spin_unlock(&card->files_lock);
return 0;

err_clear:
card->shutdown = 0;
err_unlock:
spin_unlock(&card->files_lock);
return -EINVAL;
}
EXPORT_SYMBOL_HDA(snd_hda_lock_devices);

static void hda_unlock_devices(struct snd_card *card)
void snd_hda_unlock_devices(struct hda_bus *bus)
{
struct snd_card *card = bus->card;

card = bus->card;
spin_lock(&card->files_lock);
card->shutdown = 0;
spin_unlock(&card->files_lock);
}
EXPORT_SYMBOL_HDA(snd_hda_unlock_devices);

/**
* snd_hda_codec_reset - Clear all objects assigned to the codec
Expand All @@ -2270,26 +2296,12 @@ static void hda_unlock_devices(struct snd_card *card)
*/
int snd_hda_codec_reset(struct hda_codec *codec)
{
struct snd_card *card = codec->bus->card;
int i, pcm;
struct hda_bus *bus = codec->bus;
struct snd_card *card = bus->card;
int i;

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);
if (snd_hda_lock_devices(bus) < 0)
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 */

Expand All @@ -2298,15 +2310,15 @@ int snd_hda_codec_reset(struct hda_codec *codec)
codec->power_on = 0;
codec->power_transition = 0;
codec->power_jiffies = jiffies;
flush_workqueue(codec->bus->workq);
flush_workqueue(bus->workq);
#endif
snd_hda_ctls_clear(codec);
/* relase PCMs */
for (i = 0; i < codec->num_pcms; i++) {
if (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);
bus->pcm_dev_bits);
}
}
if (codec->patch_ops.free)
Expand All @@ -2331,7 +2343,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
codec->owner = NULL;

/* allow device access again */
hda_unlock_devices(card);
snd_hda_unlock_devices(bus);
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,9 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state,
bool eapd_workaround);

int snd_hda_lock_devices(struct hda_bus *bus);
void snd_hda_unlock_devices(struct hda_bus *bus);

/*
* power management
*/
Expand Down
Loading

0 comments on commit 58823de

Please sign in to comment.