diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-02-06 08:03:20 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:07 -0400 |
commit | 7ba72ba1fe891a94b1e9d506236507e4dc50e872 (patch) | |
tree | 4c3dc43b6fbb1e9a3f28191a38da563e15180e44 /sound/pci | |
parent | 6c4cc3a8ed15aacc06a5fd369639fef633cee2bc (diff) |
[ALSA] hda-intel - Fix PCM device number assignment
In the current scheme, PCM device numbers are assigned incrementally
in the order of codecs. This causes problems when the codec number
is irregular, e.g. codec #0 for HDMI and codec #1 for analog. Then
the HDMI becomes the first PCM, which is picked up as the default
output device. Unfortuantely this doesn't work well with normal
setups.
This patch introduced the fixed device numbers for the PCM types,
namely, analog, SPDIF, HDMI and modem. The PCM devices are assigned
according to the corresponding PCM type. After this patch, HDMI will
be always assigned to PCM #3, SPDIF to PCM #1, and the first analog
to PCM #0, etc.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.h | 12 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 89 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 1 |
10 files changed, 66 insertions, 44 deletions
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index f14871151be9..301b5227bfb1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -590,11 +590,21 @@ struct hda_pcm_stream { | |||
590 | struct hda_pcm_ops ops; | 590 | struct hda_pcm_ops ops; |
591 | }; | 591 | }; |
592 | 592 | ||
593 | /* PCM types */ | ||
594 | enum { | ||
595 | HDA_PCM_TYPE_AUDIO, | ||
596 | HDA_PCM_TYPE_SPDIF, | ||
597 | HDA_PCM_TYPE_HDMI, | ||
598 | HDA_PCM_TYPE_MODEM, | ||
599 | HDA_PCM_NTYPES | ||
600 | }; | ||
601 | |||
593 | /* for PCM creation */ | 602 | /* for PCM creation */ |
594 | struct hda_pcm { | 603 | struct hda_pcm { |
595 | char *name; | 604 | char *name; |
596 | struct hda_pcm_stream stream[2]; | 605 | struct hda_pcm_stream stream[2]; |
597 | unsigned int is_modem; /* modem codec? */ | 606 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
607 | int device; /* assigned device number */ | ||
598 | }; | 608 | }; |
599 | 609 | ||
600 | /* codec information */ | 610 | /* codec information */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4be36c84b36c..18475de074b2 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -211,9 +211,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
211 | /* max buffer size - no h/w limit, you can increase as you like */ | 211 | /* max buffer size - no h/w limit, you can increase as you like */ |
212 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) | 212 | #define AZX_MAX_BUF_SIZE (1024*1024*1024) |
213 | /* max number of PCM devics per card */ | 213 | /* max number of PCM devics per card */ |
214 | #define AZX_MAX_AUDIO_PCMS 6 | 214 | #define AZX_MAX_PCMS 8 |
215 | #define AZX_MAX_MODEM_PCMS 2 | ||
216 | #define AZX_MAX_PCMS (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS) | ||
217 | 215 | ||
218 | /* RIRB int mask: overrun[2], response[0] */ | 216 | /* RIRB int mask: overrun[2], response[0] */ |
219 | #define RIRB_INT_RESPONSE 0x01 | 217 | #define RIRB_INT_RESPONSE 0x01 |
@@ -350,7 +348,6 @@ struct azx { | |||
350 | struct azx_dev *azx_dev; | 348 | struct azx_dev *azx_dev; |
351 | 349 | ||
352 | /* PCM */ | 350 | /* PCM */ |
353 | unsigned int pcm_devs; | ||
354 | struct snd_pcm *pcm[AZX_MAX_PCMS]; | 351 | struct snd_pcm *pcm[AZX_MAX_PCMS]; |
355 | 352 | ||
356 | /* HD codec */ | 353 | /* HD codec */ |
@@ -1386,7 +1383,7 @@ static void azx_pcm_free(struct snd_pcm *pcm) | |||
1386 | } | 1383 | } |
1387 | 1384 | ||
1388 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | 1385 | static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, |
1389 | struct hda_pcm *cpcm, int pcm_dev) | 1386 | struct hda_pcm *cpcm) |
1390 | { | 1387 | { |
1391 | int err; | 1388 | int err; |
1392 | struct snd_pcm *pcm; | 1389 | struct snd_pcm *pcm; |
@@ -1400,7 +1397,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1400 | 1397 | ||
1401 | snd_assert(cpcm->name, return -EINVAL); | 1398 | snd_assert(cpcm->name, return -EINVAL); |
1402 | 1399 | ||
1403 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 1400 | err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, |
1404 | cpcm->stream[0].substreams, | 1401 | cpcm->stream[0].substreams, |
1405 | cpcm->stream[1].substreams, | 1402 | cpcm->stream[1].substreams, |
1406 | &pcm); | 1403 | &pcm); |
@@ -1423,59 +1420,67 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1423 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1420 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1424 | snd_dma_pci_data(chip->pci), | 1421 | snd_dma_pci_data(chip->pci), |
1425 | 1024 * 64, 1024 * 1024); | 1422 | 1024 * 64, 1024 * 1024); |
1426 | chip->pcm[pcm_dev] = pcm; | 1423 | chip->pcm[cpcm->device] = pcm; |
1427 | if (chip->pcm_devs < pcm_dev + 1) | ||
1428 | chip->pcm_devs = pcm_dev + 1; | ||
1429 | |||
1430 | return 0; | 1424 | return 0; |
1431 | } | 1425 | } |
1432 | 1426 | ||
1433 | static int __devinit azx_pcm_create(struct azx *chip) | 1427 | static int __devinit azx_pcm_create(struct azx *chip) |
1434 | { | 1428 | { |
1429 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
1430 | "Audio", "SPDIF", "HDMI", "Modem" | ||
1431 | }; | ||
1432 | /* starting device index for each PCM type */ | ||
1433 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
1434 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
1435 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
1436 | [HDA_PCM_TYPE_HDMI] = 3, | ||
1437 | [HDA_PCM_TYPE_MODEM] = 6 | ||
1438 | }; | ||
1439 | /* normal audio device indices; not linear to keep compatibility */ | ||
1440 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
1435 | struct hda_codec *codec; | 1441 | struct hda_codec *codec; |
1436 | int c, err; | 1442 | int c, err; |
1437 | int pcm_dev; | 1443 | int num_devs[HDA_PCM_NTYPES]; |
1438 | 1444 | ||
1439 | err = snd_hda_build_pcms(chip->bus); | 1445 | err = snd_hda_build_pcms(chip->bus); |
1440 | if (err < 0) | 1446 | if (err < 0) |
1441 | return err; | 1447 | return err; |
1442 | 1448 | ||
1443 | /* create audio PCMs */ | 1449 | /* create audio PCMs */ |
1444 | pcm_dev = 0; | 1450 | memset(num_devs, 0, sizeof(num_devs)); |
1445 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1446 | for (c = 0; c < codec->num_pcms; c++) { | ||
1447 | if (codec->pcm_info[c].is_modem) | ||
1448 | continue; /* create later */ | ||
1449 | if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { | ||
1450 | snd_printk(KERN_ERR SFX | ||
1451 | "Too many audio PCMs\n"); | ||
1452 | return -EINVAL; | ||
1453 | } | ||
1454 | err = create_codec_pcm(chip, codec, | ||
1455 | &codec->pcm_info[c], pcm_dev); | ||
1456 | if (err < 0) | ||
1457 | return err; | ||
1458 | pcm_dev++; | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 | /* create modem PCMs */ | ||
1463 | pcm_dev = AZX_MAX_AUDIO_PCMS; | ||
1464 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | 1451 | list_for_each_entry(codec, &chip->bus->codec_list, list) { |
1465 | for (c = 0; c < codec->num_pcms; c++) { | 1452 | for (c = 0; c < codec->num_pcms; c++) { |
1466 | if (!codec->pcm_info[c].is_modem) | 1453 | struct hda_pcm *cpcm = &codec->pcm_info[c]; |
1467 | continue; /* already created */ | 1454 | int type = cpcm->pcm_type; |
1468 | if (pcm_dev >= AZX_MAX_PCMS) { | 1455 | switch (type) { |
1469 | snd_printk(KERN_ERR SFX | 1456 | case HDA_PCM_TYPE_AUDIO: |
1470 | "Too many modem PCMs\n"); | 1457 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { |
1471 | return -EINVAL; | 1458 | snd_printk(KERN_WARNING |
1459 | "Too many audio devices\n"); | ||
1460 | continue; | ||
1461 | } | ||
1462 | cpcm->device = audio_idx[num_devs[type]]; | ||
1463 | break; | ||
1464 | case HDA_PCM_TYPE_SPDIF: | ||
1465 | case HDA_PCM_TYPE_HDMI: | ||
1466 | case HDA_PCM_TYPE_MODEM: | ||
1467 | if (num_devs[type]) { | ||
1468 | snd_printk(KERN_WARNING | ||
1469 | "%s already defined\n", | ||
1470 | dev_name[type]); | ||
1471 | continue; | ||
1472 | } | ||
1473 | cpcm->device = dev_idx[type]; | ||
1474 | break; | ||
1475 | default: | ||
1476 | snd_printk(KERN_WARNING | ||
1477 | "Invalid PCM type %d\n", type); | ||
1478 | continue; | ||
1472 | } | 1479 | } |
1473 | err = create_codec_pcm(chip, codec, | 1480 | num_devs[type]++; |
1474 | &codec->pcm_info[c], pcm_dev); | 1481 | err = create_codec_pcm(chip, codec, cpcm); |
1475 | if (err < 0) | 1482 | if (err < 0) |
1476 | return err; | 1483 | return err; |
1477 | chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; | ||
1478 | pcm_dev++; | ||
1479 | } | 1484 | } |
1480 | } | 1485 | } |
1481 | return 0; | 1486 | return 0; |
@@ -1587,7 +1592,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1587 | int i; | 1592 | int i; |
1588 | 1593 | ||
1589 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1594 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
1590 | for (i = 0; i < chip->pcm_devs; i++) | 1595 | for (i = 0; i < AZX_MAX_PCMS; i++) |
1591 | snd_pcm_suspend_all(chip->pcm[i]); | 1596 | snd_pcm_suspend_all(chip->pcm[i]); |
1592 | if (chip->initialized) | 1597 | if (chip->initialized) |
1593 | snd_hda_suspend(chip->bus, state); | 1598 | snd_hda_suspend(chip->bus, state); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index c8649282c2cf..7286ab86ecc4 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -359,6 +359,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
359 | info++; | 359 | info++; |
360 | codec->num_pcms++; | 360 | codec->num_pcms++; |
361 | info->name = "AD198x Digital"; | 361 | info->name = "AD198x Digital"; |
362 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
362 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; | 363 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; |
363 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 364 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; |
364 | if (spec->dig_in_nid) { | 365 | if (spec->dig_in_nid) { |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 27d2e007404b..e0e9ea995684 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -116,6 +116,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec) | |||
116 | codec->pcm_info = info; | 116 | codec->pcm_info = info; |
117 | 117 | ||
118 | info->name = "ATI HDMI"; | 118 | info->name = "ATI HDMI"; |
119 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
119 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; | 120 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; |
120 | 121 | ||
121 | return 0; | 122 | return 0; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 3d6097ba1d68..99ce74b4e9fc 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -571,6 +571,7 @@ static int cmi9880_build_pcms(struct hda_codec *codec) | |||
571 | codec->num_pcms++; | 571 | codec->num_pcms++; |
572 | info++; | 572 | info++; |
573 | info->name = "CMI9880 Digital"; | 573 | info->name = "CMI9880 Digital"; |
574 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
574 | if (spec->multiout.dig_out_nid) { | 575 | if (spec->multiout.dig_out_nid) { |
575 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; | 576 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; |
576 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 577 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7206b30cbf94..bb915ede0ceb 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -284,6 +284,7 @@ static int conexant_build_pcms(struct hda_codec *codec) | |||
284 | info++; | 284 | info++; |
285 | codec->num_pcms++; | 285 | codec->num_pcms++; |
286 | info->name = "Conexant Digital"; | 286 | info->name = "Conexant Digital"; |
287 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
287 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | 288 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = |
288 | conexant_pcm_digital_playback; | 289 | conexant_pcm_digital_playback; |
289 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | 290 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 45e661e42c0b..85ea3f82de19 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2499,6 +2499,7 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2499 | codec->num_pcms = 2; | 2499 | codec->num_pcms = 2; |
2500 | info = spec->pcm_rec + 1; | 2500 | info = spec->pcm_rec + 1; |
2501 | info->name = spec->stream_name_digital; | 2501 | info->name = spec->stream_name_digital; |
2502 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
2502 | if (spec->multiout.dig_out_nid && | 2503 | if (spec->multiout.dig_out_nid && |
2503 | spec->stream_digital_playback) { | 2504 | spec->stream_digital_playback) { |
2504 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); | 2505 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index d22f5a6b850f..598ee2119bbe 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -206,7 +206,7 @@ static int si3054_build_pcms(struct hda_codec *codec) | |||
206 | info->name = "Si3054 Modem"; | 206 | info->name = "Si3054 Modem"; |
207 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm; | 207 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm; |
208 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm; | 208 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm; |
209 | info->is_modem = 1; | 209 | info->pcm_type = HDA_PCM_TYPE_MODEM; |
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | 212 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4c3c4e6ce3d6..f693011d25a0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1899,6 +1899,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
1899 | codec->num_pcms++; | 1899 | codec->num_pcms++; |
1900 | info++; | 1900 | info++; |
1901 | info->name = "STAC92xx Digital"; | 1901 | info->name = "STAC92xx Digital"; |
1902 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
1902 | if (spec->multiout.dig_out_nid) { | 1903 | if (spec->multiout.dig_out_nid) { |
1903 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | 1904 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; |
1904 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 1905 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4e5dd4cf36f5..d9a5c6a2dd9f 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -523,6 +523,7 @@ static int via_build_pcms(struct hda_codec *codec) | |||
523 | codec->num_pcms++; | 523 | codec->num_pcms++; |
524 | info++; | 524 | info++; |
525 | info->name = spec->stream_name_digital; | 525 | info->name = spec->stream_name_digital; |
526 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
526 | if (spec->multiout.dig_out_nid) { | 527 | if (spec->multiout.dig_out_nid) { |
527 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | 528 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = |
528 | *(spec->stream_digital_playback); | 529 | *(spec->stream_digital_playback); |