diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-11-24 08:31:46 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-11-26 04:19:44 -0500 |
commit | 01b65bfb4f8cd45b0d44547c961ef59a0bcf74be (patch) | |
tree | b297e5611802e0734a263718f59434d3e436e6c9 /sound | |
parent | b37c0096b448d099d304bb47c4eada9117dba4cf (diff) |
ALSA: hda - Supports more audio streams
So far, the driver supports up to 10 streams. This is a restriction in
hda_intel.c and hda_codec.c: in the former, the fixed array size limits
the amount, and in the latter, the fixed device-number assignment table
(in get_empty_pcm_device()) limits the possibility.
This patch reduces the restriction by
- using linked list for managing PCM instances in hda_intel.c, and
- assigning non-fixed device numbers for the extra devices
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 48 |
3 files changed, 30 insertions, 27 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4562e9de6a1a..4463f9a9619a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -3850,6 +3850,12 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
3850 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) | 3850 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) |
3851 | return audio_idx[type][i]; | 3851 | return audio_idx[type][i]; |
3852 | 3852 | ||
3853 | /* non-fixed slots starting from 10 */ | ||
3854 | for (i = 10; i < 32; i++) { | ||
3855 | if (!test_and_set_bit(i, bus->pcm_dev_bits)) | ||
3856 | return i; | ||
3857 | } | ||
3858 | |||
3853 | snd_printk(KERN_WARNING "Too many %s devices\n", | 3859 | snd_printk(KERN_WARNING "Too many %s devices\n", |
3854 | snd_hda_pcm_type_name[type]); | 3860 | snd_hda_pcm_type_name[type]); |
3855 | return -EAGAIN; | 3861 | return -EAGAIN; |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 564471169cae..17cee4ee8e65 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -547,9 +547,6 @@ enum { | |||
547 | /* max. codec address */ | 547 | /* max. codec address */ |
548 | #define HDA_MAX_CODEC_ADDRESS 0x0f | 548 | #define HDA_MAX_CODEC_ADDRESS 0x0f |
549 | 549 | ||
550 | /* max number of PCM devics per card */ | ||
551 | #define HDA_MAX_PCMS 10 | ||
552 | |||
553 | /* | 550 | /* |
554 | * generic arrays | 551 | * generic arrays |
555 | */ | 552 | */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9a..ddd7f3b21cdc 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -407,6 +407,14 @@ struct azx_rb { | |||
407 | u32 res[AZX_MAX_CODECS]; /* last read value */ | 407 | u32 res[AZX_MAX_CODECS]; /* last read value */ |
408 | }; | 408 | }; |
409 | 409 | ||
410 | struct azx_pcm { | ||
411 | struct azx *chip; | ||
412 | struct snd_pcm *pcm; | ||
413 | struct hda_codec *codec; | ||
414 | struct hda_pcm_stream *hinfo[2]; | ||
415 | struct list_head list; | ||
416 | }; | ||
417 | |||
410 | struct azx { | 418 | struct azx { |
411 | struct snd_card *card; | 419 | struct snd_card *card; |
412 | struct pci_dev *pci; | 420 | struct pci_dev *pci; |
@@ -434,7 +442,7 @@ struct azx { | |||
434 | struct azx_dev *azx_dev; | 442 | struct azx_dev *azx_dev; |
435 | 443 | ||
436 | /* PCM */ | 444 | /* PCM */ |
437 | struct snd_pcm *pcm[HDA_MAX_PCMS]; | 445 | struct list_head pcm_list; /* azx_pcm list */ |
438 | 446 | ||
439 | /* HD codec */ | 447 | /* HD codec */ |
440 | unsigned short codec_mask; | 448 | unsigned short codec_mask; |
@@ -1486,10 +1494,9 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1486 | azx_init_chip(chip, 1); | 1494 | azx_init_chip(chip, 1); |
1487 | #ifdef CONFIG_PM | 1495 | #ifdef CONFIG_PM |
1488 | if (chip->initialized) { | 1496 | if (chip->initialized) { |
1489 | int i; | 1497 | struct azx_pcm *p; |
1490 | 1498 | list_for_each_entry(p, &chip->pcm_list, list) | |
1491 | for (i = 0; i < HDA_MAX_PCMS; i++) | 1499 | snd_pcm_suspend_all(p->pcm); |
1492 | snd_pcm_suspend_all(chip->pcm[i]); | ||
1493 | snd_hda_suspend(chip->bus); | 1500 | snd_hda_suspend(chip->bus); |
1494 | snd_hda_resume(chip->bus); | 1501 | snd_hda_resume(chip->bus); |
1495 | } | 1502 | } |
@@ -1667,12 +1674,6 @@ static struct snd_pcm_hardware azx_pcm_hw = { | |||
1667 | .fifo_size = 0, | 1674 | .fifo_size = 0, |
1668 | }; | 1675 | }; |
1669 | 1676 | ||
1670 | struct azx_pcm { | ||
1671 | struct azx *chip; | ||
1672 | struct hda_codec *codec; | ||
1673 | struct hda_pcm_stream *hinfo[2]; | ||
1674 | }; | ||
1675 | |||
1676 | static int azx_pcm_open(struct snd_pcm_substream *substream) | 1677 | static int azx_pcm_open(struct snd_pcm_substream *substream) |
1677 | { | 1678 | { |
1678 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 1679 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
@@ -2197,7 +2198,7 @@ static void azx_pcm_free(struct snd_pcm *pcm) | |||
2197 | { | 2198 | { |
2198 | struct azx_pcm *apcm = pcm->private_data; | 2199 | struct azx_pcm *apcm = pcm->private_data; |
2199 | if (apcm) { | 2200 | if (apcm) { |
2200 | apcm->chip->pcm[pcm->device] = NULL; | 2201 | list_del(&apcm->list); |
2201 | kfree(apcm); | 2202 | kfree(apcm); |
2202 | } | 2203 | } |
2203 | } | 2204 | } |
@@ -2215,14 +2216,11 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
2215 | unsigned int size; | 2216 | unsigned int size; |
2216 | int s, err; | 2217 | int s, err; |
2217 | 2218 | ||
2218 | if (pcm_dev >= HDA_MAX_PCMS) { | 2219 | list_for_each_entry(apcm, &chip->pcm_list, list) { |
2219 | snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", | 2220 | if (apcm->pcm->device == pcm_dev) { |
2220 | pcm_dev); | 2221 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); |
2221 | return -EINVAL; | 2222 | return -EBUSY; |
2222 | } | 2223 | } |
2223 | if (chip->pcm[pcm_dev]) { | ||
2224 | snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); | ||
2225 | return -EBUSY; | ||
2226 | } | 2224 | } |
2227 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 2225 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, |
2228 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, | 2226 | cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, |
@@ -2235,12 +2233,13 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
2235 | if (apcm == NULL) | 2233 | if (apcm == NULL) |
2236 | return -ENOMEM; | 2234 | return -ENOMEM; |
2237 | apcm->chip = chip; | 2235 | apcm->chip = chip; |
2236 | apcm->pcm = pcm; | ||
2238 | apcm->codec = codec; | 2237 | apcm->codec = codec; |
2239 | pcm->private_data = apcm; | 2238 | pcm->private_data = apcm; |
2240 | pcm->private_free = azx_pcm_free; | 2239 | pcm->private_free = azx_pcm_free; |
2241 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) | 2240 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
2242 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; | 2241 | pcm->dev_class = SNDRV_PCM_CLASS_MODEM; |
2243 | chip->pcm[pcm_dev] = pcm; | 2242 | list_add_tail(&apcm->list, &chip->pcm_list); |
2244 | cpcm->pcm = pcm; | 2243 | cpcm->pcm = pcm; |
2245 | for (s = 0; s < 2; s++) { | 2244 | for (s = 0; s < 2; s++) { |
2246 | apcm->hinfo[s] = &cpcm->stream[s]; | 2245 | apcm->hinfo[s] = &cpcm->stream[s]; |
@@ -2370,12 +2369,12 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
2370 | { | 2369 | { |
2371 | struct snd_card *card = pci_get_drvdata(pci); | 2370 | struct snd_card *card = pci_get_drvdata(pci); |
2372 | struct azx *chip = card->private_data; | 2371 | struct azx *chip = card->private_data; |
2373 | int i; | 2372 | struct azx_pcm *p; |
2374 | 2373 | ||
2375 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2374 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2376 | azx_clear_irq_pending(chip); | 2375 | azx_clear_irq_pending(chip); |
2377 | for (i = 0; i < HDA_MAX_PCMS; i++) | 2376 | list_for_each_entry(p, &chip->pcm_list, list) |
2378 | snd_pcm_suspend_all(chip->pcm[i]); | 2377 | snd_pcm_suspend_all(p->pcm); |
2379 | if (chip->initialized) | 2378 | if (chip->initialized) |
2380 | snd_hda_suspend(chip->bus); | 2379 | snd_hda_suspend(chip->bus); |
2381 | azx_stop_chip(chip); | 2380 | azx_stop_chip(chip); |
@@ -2672,6 +2671,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2672 | check_msi(chip); | 2671 | check_msi(chip); |
2673 | chip->dev_index = dev; | 2672 | chip->dev_index = dev; |
2674 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | 2673 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); |
2674 | INIT_LIST_HEAD(&chip->pcm_list); | ||
2675 | 2675 | ||
2676 | chip->position_fix[0] = chip->position_fix[1] = | 2676 | chip->position_fix[0] = chip->position_fix[1] = |
2677 | check_position_fix(chip, position_fix[dev]); | 2677 | check_position_fix(chip, position_fix[dev]); |