aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-02-06 08:03:20 -0500
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:07 -0400
commit7ba72ba1fe891a94b1e9d506236507e4dc50e872 (patch)
tree4c3dc43b6fbb1e9a3f28191a38da563e15180e44 /sound/pci
parent6c4cc3a8ed15aacc06a5fd369639fef633cee2bc (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.h12
-rw-r--r--sound/pci/hda/hda_intel.c89
-rw-r--r--sound/pci/hda/patch_analog.c1
-rw-r--r--sound/pci/hda/patch_atihdmi.c1
-rw-r--r--sound/pci/hda/patch_cmedia.c1
-rw-r--r--sound/pci/hda/patch_conexant.c1
-rw-r--r--sound/pci/hda/patch_realtek.c1
-rw-r--r--sound/pci/hda/patch_si3054.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c1
-rw-r--r--sound/pci/hda/patch_via.c1
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 */
594enum {
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 */
594struct hda_pcm { 603struct 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
1388static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, 1385static 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
1433static int __devinit azx_pcm_create(struct azx *chip) 1427static 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);