[ALSA] hda-codec - Assign audio PCMS first

HDA Codec driver,HDA Intel driver,HDA generic driver
Assign audio PCMs first before modem PCMs.
The modem stream is assigned up to device #6, to be consistent over
different models.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 63a29a8..bb53bcf 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -505,6 +505,7 @@
 struct hda_pcm {
 	char *name;
 	struct hda_pcm_stream stream[2];
+	unsigned int is_modem;	/* modem codec? */
 };
 
 /* codec information */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 96f9e87..2098de7 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -164,7 +164,9 @@
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE	(1024*1024*1024)
 /* max number of PCM devics per card */
-#define AZX_MAX_PCMS		8
+#define AZX_MAX_AUDIO_PCMS	6
+#define AZX_MAX_MODEM_PCMS	2
+#define AZX_MAX_PCMS		(AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE	0x01
@@ -1225,12 +1227,33 @@
 	if ((err = snd_hda_build_pcms(chip->bus)) < 0)
 		return err;
 
+	/* create audio PCMs */
 	pcm_dev = 0;
 	list_for_each(p, &chip->bus->codec_list) {
 		codec = list_entry(p, struct hda_codec, list);
 		for (c = 0; c < codec->num_pcms; c++) {
-			if (pcm_dev >= AZX_MAX_PCMS) {
-				snd_printk(KERN_ERR SFX "Too many PCMs\n");
+			if (codec->pcm_info[c].is_modem)
+				continue; /* create later */
+			if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+				snd_printk(KERN_ERR SFX "Too many audio PCMs\n");
+				return -EINVAL;
+			}
+			err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+			if (err < 0)
+				return err;
+			pcm_dev++;
+		}
+	}
+
+	/* create modem PCMs */
+	pcm_dev = AZX_MAX_AUDIO_PCMS;
+	list_for_each(p, &chip->bus->codec_list) {
+		codec = list_entry(p, struct hda_codec, list);
+		for (c = 0; c < codec->num_pcms; c++) {
+			if (! codec->pcm_info[c].is_modem)
+				continue; /* already created */
+			if (pcm_dev >= AZX_MAX_MODEM_PCMS) {
+				snd_printk(KERN_ERR SFX "Too many modem PCMs\n");
 				return -EINVAL;
 			}
 			err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index de1217b..08f6a6e 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -207,6 +207,8 @@
 	snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
 	snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+	if (! codec->afg)
+		return;
 	snd_iprintf(buffer, "Default PCM: ");
 	print_pcm_caps(buffer, codec, codec->afg);
 	snd_iprintf(buffer, "Default Amp-In caps: ");
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index b0270d1..c41fb9a 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -214,6 +214,7 @@
 	info->name = "Si3054 Modem";
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
 	info->stream[SNDRV_PCM_STREAM_CAPTURE]  = si3054_pcm;
+	info->is_modem = 1;
 	return 0;
 }